aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJames Ahlborn <jtahlborn@yahoo.com>2007-12-02 04:29:59 +0000
committerJames Ahlborn <jtahlborn@yahoo.com>2007-12-02 04:29:59 +0000
commitbca9319ef7c3fba0ee234d2ba8152de6fe0d1329 (patch)
tree2a8b859f6a325b1febeeb8e09367875f08d0d202 /src
parent5cd19292eb5178343233bd6e5ef2ce8367b443ff (diff)
downloadjackcess-bca9319ef7c3fba0ee234d2ba8152de6fe0d1329.tar.gz
jackcess-bca9319ef7c3fba0ee234d2ba8152de6fe0d1329.zip
implement range-based, index cursors
git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/trunk@194 f203690c-595d-4dc9-a70b-905162fa7fd2
Diffstat (limited to 'src')
-rw-r--r--src/java/com/healthmarketscience/jackcess/Cursor.java149
-rw-r--r--src/java/com/healthmarketscience/jackcess/Index.java191
-rw-r--r--src/java/com/healthmarketscience/jackcess/Table.java7
-rw-r--r--src/java/com/healthmarketscience/jackcess/UsageMap.java29
4 files changed, 263 insertions, 113 deletions
diff --git a/src/java/com/healthmarketscience/jackcess/Cursor.java b/src/java/com/healthmarketscience/jackcess/Cursor.java
index 3bba37e..520481a 100644
--- a/src/java/com/healthmarketscience/jackcess/Cursor.java
+++ b/src/java/com/healthmarketscience/jackcess/Cursor.java
@@ -30,27 +30,20 @@ public abstract class Cursor implements Iterable<Map<String, Object>>
{
private static final Log LOG = LogFactory.getLog(Cursor.class);
- /** normal first position for the TableScanCursor */
+ /** first position for the TableScanCursor */
private static final ScanPosition FIRST_SCAN_POSITION =
new ScanPosition(RowId.FIRST_ROW_ID);
- /** normal last position for the TableScanCursor */
+ /** last position for the TableScanCursor */
private static final ScanPosition LAST_SCAN_POSITION =
new ScanPosition(RowId.LAST_ROW_ID);
- /** normal first position for the IndexCursor */
- private static final IndexPosition FIRST_INDEX_POSITION =
- new IndexPosition(Index.FIRST_ENTRY);
- /** normal last position for the IndexCursor */
- private static final IndexPosition LAST_INDEX_POSITION =
- new IndexPosition(Index.LAST_ENTRY);
-
/** owning table */
private final Table _table;
/** State used for reading the table rows */
private final RowState _rowState;
- /** the first (exclusive) row id for this iterator */
+ /** the first (exclusive) row id for this cursor */
private final Position _firstPos;
- /** the last (exclusive) row id for this iterator */
+ /** the last (exclusive) row id for this cursor */
private final Position _lastPos;
/** the previous row */
private Position _prevPos;
@@ -84,7 +77,54 @@ public abstract class Cursor implements Iterable<Map<String, Object>>
public static Cursor createIndexCursor(Table table, Index index)
throws IOException
{
- return new IndexCursor(table, index);
+ return createIndexCursor(table, index, null, null);
+ }
+
+ /**
+ * Creates an indexed cursor for the given table, narrowed to the given
+ * range.
+ * @param table the table over which this cursor will traverse
+ * @param index index for the table which will define traversal order as
+ * well as enhance certain lookups
+ * @param startRow the first row of data for the cursor (inclusive), or
+ * {@code null} for the first entry
+ * @param endRow the last row of data for the cursor (inclusive), or
+ * {@code null} for the last entry
+ */
+ public static Cursor createIndexCursor(Table table, Index index,
+ Object[] startRow, Object[] endRow)
+ throws IOException
+ {
+ return createIndexCursor(table, index, startRow, true, endRow, true);
+ }
+
+ /**
+ * Creates an indexed cursor for the given table, narrowed to the given
+ * range.
+ * @param table the table over which this cursor will traverse
+ * @param index index for the table which will define traversal order as
+ * well as enhance certain lookups
+ * @param startRow the first row of data for the cursor, or {@code null} for
+ * the first entry
+ * @param startInclusive whether or not startRow is inclusive or exclusive
+ * @param endRow the last row of data for the cursor, or {@code null} for
+ * the last entry
+ * @param endInclusive whether or not endRow is inclusive or exclusive
+ */
+ public static Cursor createIndexCursor(Table table, Index index,
+ Object[] startRow,
+ boolean startInclusive,
+ Object[] endRow,
+ boolean endInclusive)
+ throws IOException
+ {
+ if(table != index.getTable()) {
+ throw new IllegalArgumentException(
+ "Given index is not for given table: " + index + ", " + table);
+ }
+ return new IndexCursor(table, index,
+ index.cursor(startRow, startInclusive,
+ endRow, endInclusive));
}
/**
@@ -209,11 +249,11 @@ public abstract class Cursor implements Iterable<Map<String, Object>>
* Moves the cursor to a savepoint previously returned from
* {@link #getSavepoint}.
*/
- public void restoreSavepoint(Savepoint savepoint)
+ public Cursor restoreSavepoint(Savepoint savepoint)
throws IOException
{
- restorePosition(savepoint.getCurrentPosition(),
- savepoint.getPreviousPosition());
+ return restorePosition(savepoint.getCurrentPosition(),
+ savepoint.getPreviousPosition());
}
/**
@@ -231,26 +271,26 @@ public abstract class Cursor implements Iterable<Map<String, Object>>
}
/**
- * Resets this cursor for forward iteration. Calls {@link #beforeFirst}.
+ * Resets this cursor for forward traversal. Calls {@link #beforeFirst}.
*/
- public void reset() {
- beforeFirst();
+ public Cursor reset() {
+ return beforeFirst();
}
/**
- * Resets this cursor for forward iteration (sets cursor to before the first
+ * Resets this cursor for forward traversal (sets cursor to before the first
* row).
*/
- public void beforeFirst() {
- reset(true);
+ public Cursor beforeFirst() {
+ return reset(true);
}
/**
- * Resets this cursor for reverse iteration (sets cursor to after the last
+ * Resets this cursor for reverse traversal (sets cursor to after the last
* row).
*/
- public void afterLast() {
- reset(false);
+ public Cursor afterLast() {
+ return reset(false);
}
/**
@@ -293,12 +333,13 @@ public abstract class Cursor implements Iterable<Map<String, Object>>
}
/**
- * Resets this cursor for iterating the given direction.
+ * Resets this cursor for traversing the given direction.
*/
- protected void reset(boolean moveForward) {
+ protected Cursor reset(boolean moveForward) {
_curPos = getDirHandler(moveForward).getBeginningPosition();
_prevPos = _curPos;
_rowState.reset();
+ return this;
}
/**
@@ -470,27 +511,38 @@ public abstract class Cursor implements Iterable<Map<String, Object>>
* Restores a current position for the cursor (current position becomes
* previous position).
*/
- protected void restorePosition(Position curPos)
+ protected Cursor restorePosition(Position curPos)
throws IOException
{
- restorePosition(curPos, _curPos);
+ return restorePosition(curPos, _curPos);
}
/**
- * Restores a current and previous position for the cursor.
+ * Restores a current and previous position for the cursor if the given
+ * positions are different from the current positions.
*/
- protected void restorePosition(Position curPos, Position prevPos)
+ protected final Cursor restorePosition(Position curPos, Position prevPos)
throws IOException
{
if(!curPos.equals(_curPos) || !prevPos.equals(_prevPos)) {
- // make the current position previous, and the new position current
- _prevPos = _curPos;
- _curPos = curPos;
- _rowState.reset();
+ restorePositionImpl(curPos, prevPos);
}
+ return this;
}
/**
+ * Restores a current and previous position for the cursor.
+ */
+ protected void restorePositionImpl(Position curPos, Position prevPos)
+ throws IOException
+ {
+ // make the current position previous, and the new position current
+ _prevPos = _curPos;
+ _curPos = curPos;
+ _rowState.reset();
+ }
+
+ /**
* Rechecks the current position if the underlying data structures have been
* modified.
* @return {@code true} if the cursor ended up in a new position,
@@ -815,13 +867,13 @@ public abstract class Cursor implements Iterable<Map<String, Object>>
}
@Override
- protected void reset(boolean moveForward) {
+ protected Cursor reset(boolean moveForward) {
_ownedPagesCursor.reset(moveForward);
- super.reset(moveForward);
+ return super.reset(moveForward);
}
@Override
- protected void restorePosition(Position curPos, Position prevPos)
+ protected void restorePositionImpl(Position curPos, Position prevPos)
throws IOException
{
if(!(curPos instanceof ScanPosition) ||
@@ -829,9 +881,9 @@ public abstract class Cursor implements Iterable<Map<String, Object>>
throw new IllegalArgumentException(
"Restored positions must be scan positions");
}
- super.restorePosition(curPos, prevPos);
_ownedPagesCursor.restorePosition(curPos.getRowId().getPageNumber(),
prevPos.getRowId().getPageNumber());
+ super.restorePositionImpl(curPos, prevPos);
}
@Override
@@ -957,15 +1009,14 @@ public abstract class Cursor implements Iterable<Map<String, Object>>
/** Cursor over the entries of the relvant index */
private final Index.EntryCursor _entryCursor;
- private IndexCursor(Table table, Index index)
+ private IndexCursor(Table table, Index index,
+ Index.EntryCursor entryCursor)
throws IOException
{
- super(table, FIRST_INDEX_POSITION, LAST_INDEX_POSITION);
- if(table != index.getTable()) {
- throw new IllegalArgumentException(
- "Given index is not for given table: " + index + ", " + table);
- }
- _entryCursor = index.cursor();
+ super(table,
+ new IndexPosition(entryCursor.getFirstEntry()),
+ new IndexPosition(entryCursor.getLastEntry()));
+ _entryCursor = entryCursor;
}
@Override
@@ -979,13 +1030,13 @@ public abstract class Cursor implements Iterable<Map<String, Object>>
}
@Override
- protected void reset(boolean moveForward) {
+ protected Cursor reset(boolean moveForward) {
_entryCursor.reset(moveForward);
- super.reset(moveForward);
+ return super.reset(moveForward);
}
@Override
- protected void restorePosition(Position curPos, Position prevPos)
+ protected void restorePositionImpl(Position curPos, Position prevPos)
throws IOException
{
if(!(curPos instanceof IndexPosition) ||
@@ -993,9 +1044,9 @@ public abstract class Cursor implements Iterable<Map<String, Object>>
throw new IllegalArgumentException(
"Restored positions must be index positions");
}
- super.restorePosition(curPos, prevPos);
_entryCursor.restorePosition(((IndexPosition)curPos).getEntry(),
((IndexPosition)prevPos).getEntry());
+ super.restorePositionImpl(curPos, prevPos);
}
@Override
diff --git a/src/java/com/healthmarketscience/jackcess/Index.java b/src/java/com/healthmarketscience/jackcess/Index.java
index 7aed345..fe12832 100644
--- a/src/java/com/healthmarketscience/jackcess/Index.java
+++ b/src/java/com/healthmarketscience/jackcess/Index.java
@@ -597,8 +597,46 @@ public class Index implements Comparable<Index> {
public EntryCursor cursor()
throws IOException
{
+ return cursor(null, true, null, true);
+ }
+
+ /**
+ * Gets a new cursor for this index, narrowed to the range defined by the
+ * given startRow and endRow.
+ * <p>
+ * Forces index initialization.
+ *
+ * @param startRow the first row of data for the cursor, or {@code null} for
+ * the first entry
+ * @param startInclusive whether or not startRow is inclusive or exclusive
+ * @param endRow the last row of data for the cursor, or {@code null} for
+ * the last entry
+ * @param endInclusive whether or not endRow is inclusive or exclusive
+ */
+ public EntryCursor cursor(Object[] startRow,
+ boolean startInclusive,
+ Object[] endRow,
+ boolean endInclusive)
+ throws IOException
+ {
initialize();
- return new EntryCursor();
+ Position startPos = FIRST_POSITION;
+ if(startRow != null) {
+ Entry startEntry = new Entry(startRow,
+ (startInclusive ?
+ RowId.FIRST_ROW_ID : RowId.LAST_ROW_ID),
+ _columns);
+ startPos = new Position(FIRST_ENTRY_IDX, startEntry);
+ }
+ Position endPos = LAST_POSITION;
+ if(endRow != null) {
+ Entry endEntry = new Entry(endRow,
+ (endInclusive ?
+ RowId.LAST_ROW_ID : RowId.FIRST_ROW_ID),
+ _columns);
+ endPos = new Position(LAST_ENTRY_IDX, endEntry);
+ }
+ return new EntryCursor(startPos, endPos);
}
/**
@@ -1413,11 +1451,28 @@ public class Index implements Comparable<Index> {
private final DirHandler _forwardDirHandler = new ForwardDirHandler();
/** handler for moving the page cursor backward */
private final DirHandler _reverseDirHandler = new ReverseDirHandler();
+ /** the first (exclusive) row id for this cursor */
+ private final Position _firstPos;
+ /** the last (exclusive) row id for this cursor */
+ private final Position _lastPos;
+ /** the first valid index for this cursor */
+ private int _minIndex;
+ /** the last valid index for this cursor */
+ private int _maxIndex;
+ /** the current entry */
private Position _curPos;
+ /** the previous entry */
private Position _prevPos;
+ /** the last read modification count on the Index. we track this so that
+ the cursor can detect updates to the index while traversing and act
+ accordingly */
private int _lastModCount;
- private EntryCursor() {
+ private EntryCursor(Position firstPos, Position lastPos) {
+ _firstPos = firstPos;
+ _lastPos = lastPos;
+ // force bounds to be updated
+ _lastModCount = Index.this._modCount - 1;
reset();
}
@@ -1426,6 +1481,20 @@ public class Index implements Comparable<Index> {
}
/**
+ * Returns the first entry (exclusive) as defined by this cursor.
+ */
+ public Entry getFirstEntry() {
+ return _firstPos.getEntry();
+ }
+
+ /**
+ * Returns the last entry (exclusive) as defined by this cursor.
+ */
+ public Entry getLastEntry() {
+ return _lastPos.getEntry();
+ }
+
+ /**
* Returns the DirHandler for the given direction
*/
private DirHandler getDirHandler(boolean moveForward) {
@@ -1440,55 +1509,60 @@ public class Index implements Comparable<Index> {
return(Index.this._modCount == _lastModCount);
}
- public void reset() {
- beforeFirst();
+ public EntryCursor reset() {
+ return beforeFirst();
}
- public void beforeFirst() {
- reset(true);
+ public EntryCursor beforeFirst() {
+ return reset(true);
}
- public void afterLast() {
- reset(false);
+ public EntryCursor afterLast() {
+ return reset(false);
}
- protected void reset(boolean moveForward) {
+ protected EntryCursor reset(boolean moveForward) {
_curPos = getDirHandler(moveForward).getBeginningPosition();
_prevPos = _curPos;
- _lastModCount = Index.this._modCount;
+ if(!isUpToDate()) {
+ // update bounds
+ updateBounds();
+ _lastModCount = Index.this._modCount;
+ }
+ return this;
}
/**
* Repositions the cursor so that the next row will be the first entry
* >= the given row.
*/
- public void beforeEntry(Object[] row)
+ public EntryCursor beforeEntry(Object[] row)
throws IOException
{
- restorePosition(new Entry(row, RowId.FIRST_ROW_ID, _columns));
+ return restorePosition(new Entry(row, RowId.FIRST_ROW_ID, _columns));
}
/**
* Repositions the cursor so that the previous row will be the first
* entry <= the given row.
*/
- public void afterEntry(Object[] row)
+ public EntryCursor afterEntry(Object[] row)
throws IOException
{
- restorePosition(new Entry(row, RowId.LAST_ROW_ID, _columns));
+ return restorePosition(new Entry(row, RowId.LAST_ROW_ID, _columns));
}
/**
- * @return valid entry if there was entry, {@link Index#LAST_ENTRY}
- * otherwise
+ * @return valid entry if there was a next entry,
+ * {@code #getLastEntry} otherwise
*/
public Entry getNextEntry() {
return getAnotherEntry(true);
}
/**
- * @return valid entry if there was entry, {@link Index#FIRST_ENTRY}
- * otherwise
+ * @return valid entry if there was a next entry,
+ * {@code #getFirstEntry} otherwise
*/
public Entry getPreviousEntry() {
return getAnotherEntry(false);
@@ -1498,63 +1572,90 @@ public class Index implements Comparable<Index> {
* Restores a current position for the cursor (current position becomes
* previous position).
*/
- private void restorePosition(Entry curEntry) {
- restorePosition(curEntry, _curPos.getEntry());
+ private EntryCursor restorePosition(Entry curEntry) {
+ return restorePosition(curEntry, _curPos.getEntry());
}
/**
* Restores a current and previous position for the cursor.
*/
- protected void restorePosition(Entry curEntry, Entry prevEntry)
+ protected EntryCursor restorePosition(Entry curEntry, Entry prevEntry)
{
if(!curEntry.equals(_curPos.getEntry()) ||
!prevEntry.equals(_prevPos.getEntry()))
{
_prevPos = updatePosition(prevEntry);
_curPos = updatePosition(curEntry);
- _lastModCount = Index.this._modCount;
+ if(!isUpToDate()) {
+ updateBounds();
+ _lastModCount = Index.this._modCount;
+ }
} else {
checkForModification();
}
+ return this;
}
/**
- * Checks the index for modifications an updates state accordingly.
+ * Checks the index for modifications and updates state accordingly.
*/
private void checkForModification() {
if(!isUpToDate()) {
_prevPos = updatePosition(_prevPos.getEntry());
_curPos = updatePosition(_curPos.getEntry());
+ updateBounds();
_lastModCount = Index.this._modCount;
}
}
+ private void updateBounds() {
+ int idx = findEntry(_firstPos.getEntry());
+ if(idx < 0) {
+ idx = missingIndexToInsertionPoint(idx);
+ }
+ _minIndex = idx;
+
+ idx = findEntry(_lastPos.getEntry());
+ if(idx < 0) {
+ idx = missingIndexToInsertionPoint(idx) - 1;
+ }
+ _maxIndex = idx;
+ }
+
/**
* Gets an up-to-date position for the given entry.
*/
private Position updatePosition(Entry entry) {
- int curIdx = FIRST_ENTRY_IDX;
- boolean between = false;
if(entry.isValid()) {
+
// find the new position for this entry
- int idx = findEntry(entry);
- if(idx >= 0) {
- curIdx = idx;
- } else {
+ int curIdx = findEntry(entry);
+ boolean between = false;
+ if(curIdx < 0) {
// given entry was not found exactly. our current position is now
// really between two indexes, but we cannot support that as an
// integer value so we set a flag instead
- curIdx = missingIndexToInsertionPoint(idx);
+ curIdx = missingIndexToInsertionPoint(curIdx);
between = true;
}
- } else if(entry.equals(FIRST_ENTRY)) {
- curIdx = FIRST_ENTRY_IDX;
- } else if(entry.equals(LAST_ENTRY)) {
- curIdx = LAST_ENTRY_IDX;
+
+ if(curIdx < _minIndex) {
+ curIdx = _minIndex;
+ between = true;
+ } else if(curIdx > _maxIndex) {
+ curIdx = _maxIndex + 1;
+ between = true;
+ }
+
+ return new Position(curIdx, entry, between);
+
+ } else if(entry.equals(_firstPos.getEntry())) {
+ return _firstPos;
+ } else if(entry.equals(_lastPos.getEntry())) {
+ return _lastPos;
} else {
throw new IllegalArgumentException("Invalid entry given: " + entry);
}
- return new Position(curIdx, entry, between);
}
/**
@@ -1598,12 +1699,12 @@ public class Index implements Comparable<Index> {
return new Position(curIdx, _entries.get(curIdx));
}
protected final Position newForwardPosition(int curIdx) {
- return((curIdx < _entries.size()) ?
- newPosition(curIdx) : LAST_POSITION);
+ return((curIdx <= _maxIndex) ?
+ newPosition(curIdx) : _lastPos);
}
protected final Position newReversePosition(int curIdx) {
- return ((curIdx >= 0) ?
- newPosition(curIdx) : FIRST_POSITION);
+ return ((curIdx >= _minIndex) ?
+ newPosition(curIdx) : _firstPos);
}
}
@@ -1617,17 +1718,17 @@ public class Index implements Comparable<Index> {
// between position
if(!between) {
curIdx = ((curIdx == getBeginningPosition().getIndex()) ?
- 0 : (curIdx + 1));
+ _minIndex : (curIdx + 1));
}
return newForwardPosition(curIdx);
}
@Override
public Position getBeginningPosition() {
- return FIRST_POSITION;
+ return _firstPos;
}
@Override
public Position getEndPosition() {
- return LAST_POSITION;
+ return _lastPos;
}
}
@@ -1641,16 +1742,16 @@ public class Index implements Comparable<Index> {
// pointing at the correct next index in either the between or
// non-between case
curIdx = ((curIdx == getBeginningPosition().getIndex()) ?
- (_entries.size() - 1) : (curIdx - 1));
+ _maxIndex : (curIdx - 1));
return newReversePosition(curIdx);
}
@Override
public Position getBeginningPosition() {
- return LAST_POSITION;
+ return _lastPos;
}
@Override
public Position getEndPosition() {
- return FIRST_POSITION;
+ return _firstPos;
}
}
}
diff --git a/src/java/com/healthmarketscience/jackcess/Table.java b/src/java/com/healthmarketscience/jackcess/Table.java
index 08c7d4a..830b17c 100644
--- a/src/java/com/healthmarketscience/jackcess/Table.java
+++ b/src/java/com/healthmarketscience/jackcess/Table.java
@@ -39,7 +39,6 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
-import com.healthmarketscience.jackcess.Table.RowState;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -1048,7 +1047,7 @@ public class Table
// find last data page (Not bothering to check other pages for free
// space.)
- UsageMap.PageCursor revPageCursor = _ownedPages.cursorAtEnd();
+ UsageMap.PageCursor revPageCursor = _ownedPages.cursor().afterLast();
while(true) {
int tmpPageNumber = revPageCursor.getPreviousPage();
if(tmpPageNumber < 0) {
@@ -1486,7 +1485,9 @@ public class Table
private boolean _haveRowValues;
/** values read from the last row */
private final Object[] _rowValues;
- /** last modification count seen on the table */
+ /** last modification count seen on the table we track this so that the
+ rowState can detect updates to the table and re-read any buffered
+ data */
private int _lastModCount;
private RowState(boolean hardRowBuffer) {
diff --git a/src/java/com/healthmarketscience/jackcess/UsageMap.java b/src/java/com/healthmarketscience/jackcess/UsageMap.java
index 231267a..79e772e 100644
--- a/src/java/com/healthmarketscience/jackcess/UsageMap.java
+++ b/src/java/com/healthmarketscience/jackcess/UsageMap.java
@@ -147,12 +147,6 @@ public class UsageMap
return new PageCursor();
}
- public PageCursor cursorAtEnd() {
- PageCursor cursor = new PageCursor();
- cursor.afterLast();
- return cursor;
- }
-
protected short getRowStart() {
return _rowStart;
}
@@ -784,48 +778,50 @@ public class UsageMap
* After calling this method, getNextPage will return the first page in
* the map
*/
- public void reset() {
- beforeFirst();
+ public PageCursor reset() {
+ return beforeFirst();
}
/**
* After calling this method, {@link #getNextPage} will return the first
* page in the map
*/
- public void beforeFirst() {
- reset(true);
+ public PageCursor beforeFirst() {
+ return reset(true);
}
/**
* After calling this method, {@link #getPreviousPage} will return the
* last page in the map
*/
- public void afterLast() {
- reset(false);
+ public PageCursor afterLast() {
+ return reset(false);
}
/**
* Resets this page cursor for traversing the given direction.
*/
- protected void reset(boolean moveForward) {
+ protected PageCursor reset(boolean moveForward) {
_curPageNumber = getDirHandler(moveForward).getBeginningPageNumber();
_prevPageNumber = _curPageNumber;
_lastModCount = UsageMap.this._modCount;
+ return this;
}
/**
* Restores a current position for the cursor (current position becomes
* previous position).
*/
- private void restorePosition(int curPageNumber)
+ private PageCursor restorePosition(int curPageNumber)
{
- restorePosition(curPageNumber, _curPageNumber);
+ return restorePosition(curPageNumber, _curPageNumber);
}
/**
* Restores a current and previous position for the cursor.
*/
- protected void restorePosition(int curPageNumber, int prevPageNumber) {
+ protected PageCursor restorePosition(int curPageNumber, int prevPageNumber)
+ {
if((curPageNumber != _curPageNumber) ||
(prevPageNumber != _prevPageNumber))
{
@@ -835,6 +831,7 @@ public class UsageMap
} else {
checkForModification();
}
+ return this;
}
/**