aboutsummaryrefslogtreecommitdiffstats
path: root/src/java/com/healthmarketscience/jackcess/UsageMap.java
diff options
context:
space:
mode:
authorJames Ahlborn <jtahlborn@yahoo.com>2007-11-21 15:10:48 +0000
committerJames Ahlborn <jtahlborn@yahoo.com>2007-11-21 15:10:48 +0000
commit01c8f369cfa93ac9fbe54f177006fa29d846d3e7 (patch)
tree005b859db9752d3659341a62cbfebe6d0f36fe31 /src/java/com/healthmarketscience/jackcess/UsageMap.java
parente39f2d1d3d4d752a276daff7710a9d91a590930b (diff)
downloadjackcess-01c8f369cfa93ac9fbe54f177006fa29d846d3e7.tar.gz
jackcess-01c8f369cfa93ac9fbe54f177006fa29d846d3e7.zip
add reverse cursor traversal
git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/trunk@179 f203690c-595d-4dc9-a70b-905162fa7fd2
Diffstat (limited to 'src/java/com/healthmarketscience/jackcess/UsageMap.java')
-rw-r--r--src/java/com/healthmarketscience/jackcess/UsageMap.java214
1 files changed, 153 insertions, 61 deletions
diff --git a/src/java/com/healthmarketscience/jackcess/UsageMap.java b/src/java/com/healthmarketscience/jackcess/UsageMap.java
index 3305f11..07d711f 100644
--- a/src/java/com/healthmarketscience/jackcess/UsageMap.java
+++ b/src/java/com/healthmarketscience/jackcess/UsageMap.java
@@ -143,11 +143,13 @@ public class UsageMap
}
public PageIterator iterator() {
- return new ForwardPageIterator();
+ return new PageIterator();
}
- public PageIterator reverseIterator() {
- return new ReversePageIterator();
+ public PageIterator iteratorAtEnd() {
+ PageIterator iterator = new PageIterator();
+ iterator.afterLast();
+ return iterator;
}
protected short getRowStart() {
@@ -679,8 +681,12 @@ public class UsageMap
* iterators hold on to page numbers, they should stay valid even as the
* usage map handlers shift around the bits.
*/
- public abstract class PageIterator
+ public class PageIterator
{
+ /** handler for moving the page iterator forward */
+ private final DirHandler _forwardDirHandler = new ForwardDirHandler();
+ /** handler for moving the page iterator backward */
+ private final DirHandler _reverseDirHandler = new ReverseDirHandler();
/** the next used page number */
private int _nextPageNumber;
/** the previous used page number */
@@ -690,26 +696,53 @@ public class UsageMap
and act accordingly */
private int _lastModCount;
- protected PageIterator() {
+ private PageIterator() {
+ reset();
}
/**
- * @return {@code true} if there is another valid page, {@code false}
- * otherwise.
+ * Returns the DirHandler for the given direction
+ */
+ private DirHandler getDirHandler(boolean moveForward) {
+ return (moveForward ? _forwardDirHandler : _reverseDirHandler);
+ }
+
+ /**
+ * @return {@code true} if there is another valid page after the current
+ * page, {@code false} otherwise.
*/
public final boolean hasNextPage() {
- if((_nextPageNumber == PageChannel.INVALID_PAGE_NUMBER) &&
- (_lastModCount != _modCount)) {
+ return hasAnotherPage(true);
+ }
+
+ /**
+ * @return {@code true} if there is another valid page before the current
+ * page, {@code false} otherwise.
+ */
+ public final boolean hasPreviousPage() {
+ return hasAnotherPage(false);
+ }
+
+ private boolean hasAnotherPage(boolean moveForward) {
+ DirHandler handler = getDirHandler(moveForward);
+ int curPageNumber = handler.getCurrentPageNumber();
+ int otherPageNumber = handler.getOtherPageNumber();
+
+ if((curPageNumber == PageChannel.INVALID_PAGE_NUMBER) &&
+ (_lastModCount != UsageMap.this._modCount)) {
// recheck the last page, in case more showed up
- if(_prevPageNumber == PageChannel.INVALID_PAGE_NUMBER) {
+ if(otherPageNumber == PageChannel.INVALID_PAGE_NUMBER) {
// we were at the beginning
- reset();
+ reset(moveForward);
} else {
- _lastModCount = _modCount;
- _nextPageNumber = getNextPage(_prevPageNumber);
+ // we were at the end
+ _lastModCount = UsageMap.this._modCount;
+ handler.setCurrentPageNumber(
+ handler.getAnotherPageNumber(otherPageNumber));
}
+ curPageNumber = handler.getCurrentPageNumber();
}
- return(_nextPageNumber != PageChannel.INVALID_PAGE_NUMBER);
+ return(curPageNumber != PageChannel.INVALID_PAGE_NUMBER);
}
/**
@@ -717,69 +750,128 @@ public class UsageMap
* {@link PageChannel#INVALID_PAGE_NUMBER} otherwise
*/
public final int getNextPage() {
- if (hasNextPage()) {
- _lastModCount = _modCount;
- _prevPageNumber = _nextPageNumber;
- _nextPageNumber = getNextPage(_nextPageNumber);
- return _prevPageNumber;
+ return getAnotherPage(true);
+ }
+
+ /**
+ * @return valid page number if there was another page to read,
+ * {@link PageChannel#INVALID_PAGE_NUMBER} otherwise
+ */
+ public final int getPreviousPage() {
+ return getAnotherPage(false);
+ }
+
+ /**
+ * Gets another page in the given direction, returning the current page.
+ */
+ private int getAnotherPage(boolean moveForward) {
+ if (hasAnotherPage(moveForward)) {
+ _lastModCount = UsageMap.this._modCount;
+ DirHandler handler = getDirHandler(moveForward);
+ int anotherPage = handler.getCurrentPageNumber();
+ handler.setOtherPageNumber(anotherPage);
+ handler.setCurrentPageNumber(
+ handler.getAnotherPageNumber(anotherPage));
+ return anotherPage;
}
return PageChannel.INVALID_PAGE_NUMBER;
}
-
+
/**
* After calling this method, getNextPage will return the first page in
* the map
*/
public final void reset() {
- _lastModCount = _modCount;
- _prevPageNumber = PageChannel.INVALID_PAGE_NUMBER;
- _nextPageNumber = getInitialPage();
+ beforeFirst();
}
- protected abstract int getInitialPage();
-
- protected abstract int getNextPage(int curPage);
- }
-
- /**
- * Utility class to iterate forward over the pages in the UsageMap.
- */
- public class ForwardPageIterator extends PageIterator
- {
- private ForwardPageIterator() {
- reset();
+ /**
+ * After calling this method, {@link #getNextPage} will return the first
+ * page in the map
+ */
+ public void beforeFirst() {
+ reset(true);
}
-
- @Override
- protected int getNextPage(int curPage) {
- return UsageMap.this.getNextPageNumber(curPage);
+
+ /**
+ * After calling this method, {@link #getPreviousPage} will return the
+ * last page in the map
+ */
+ public void afterLast() {
+ reset(false);
}
- @Override
- protected int getInitialPage() {
- return UsageMap.this.getFirstPageNumber();
+ /**
+ * Resets this page iterator for iterating the given direction.
+ */
+ protected void reset(boolean moveForward) {
+ _lastModCount = UsageMap.this._modCount;
+ getDirHandler(moveForward).reset();
}
- }
-
- /**
- * Utility class to iterate backward over the pages in the UsageMap.
- */
- public class ReversePageIterator extends PageIterator
- {
- private ReversePageIterator() {
- reset();
+
+ /**
+ * Handles moving the iterator in a given direction. Separates iterator
+ * logic from value storage.
+ */
+ private abstract class DirHandler {
+ public abstract int getCurrentPageNumber();
+ public abstract void setCurrentPageNumber(int newPageNumber);
+ public abstract int getOtherPageNumber();
+ public abstract void setOtherPageNumber(int newPageNumber);
+ public abstract int getAnotherPageNumber(int curPageNumber);
+ public abstract void reset();
}
-
- @Override
- protected int getNextPage(int curPage) {
- return UsageMap.this.getPrevPageNumber(curPage);
+
+ /**
+ * Handles moving the iterator forward.
+ */
+ private final class ForwardDirHandler extends DirHandler {
+ public int getCurrentPageNumber() {
+ return _nextPageNumber;
+ }
+ public void setCurrentPageNumber(int newPageNumber) {
+ _nextPageNumber = newPageNumber;
+ }
+ public int getOtherPageNumber() {
+ return _prevPageNumber;
+ }
+ public void setOtherPageNumber(int newPageNumber) {
+ _prevPageNumber = newPageNumber;
+ }
+ public int getAnotherPageNumber(int curPageNumber) {
+ return UsageMap.this.getNextPageNumber(curPageNumber);
+ }
+ public void reset() {
+ _nextPageNumber = UsageMap.this.getFirstPageNumber();
+ _prevPageNumber = PageChannel.INVALID_PAGE_NUMBER;
+ }
}
-
- @Override
- protected int getInitialPage() {
- return UsageMap.this.getLastPageNumber();
+
+ /**
+ * Handles moving the iterator backward.
+ */
+ private final class ReverseDirHandler extends DirHandler {
+ public int getCurrentPageNumber() {
+ return _prevPageNumber;
+ }
+ public void setCurrentPageNumber(int newPageNumber) {
+ _prevPageNumber = newPageNumber;
+ }
+ public int getOtherPageNumber() {
+ return _nextPageNumber;
+ }
+ public void setOtherPageNumber(int newPageNumber) {
+ _nextPageNumber = newPageNumber;
+ }
+ public int getAnotherPageNumber(int curPageNumber) {
+ return UsageMap.this.getPrevPageNumber(curPageNumber);
+ }
+ public void reset() {
+ _nextPageNumber = PageChannel.INVALID_PAGE_NUMBER;
+ _prevPageNumber = UsageMap.this.getLastPageNumber();
+ }
}
- }
-
+
+ }
}