1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.healthmarketscience.jackcess.impl;
18
19 import java.io.IOException;
20
21 import com.healthmarketscience.jackcess.impl.TableImpl.RowState;
22
23
24
25
26
27
28
29 public class TableScanCursor extends CursorImpl
30 {
31
32 private static final ScanPosition FIRST_SCAN_POSITION =
33 new ScanPosition(RowIdImpl.FIRST_ROW_ID);
34
35 private static final ScanPosition LAST_SCAN_POSITION =
36 new ScanPosition(RowIdImpl.LAST_ROW_ID);
37
38
39
40 private final ScanDirHandler _forwardDirHandler =
41 new ForwardScanDirHandler();
42
43 private final ScanDirHandler _reverseDirHandler =
44 new ReverseScanDirHandler();
45
46 private final UsageMap.PageCursor _ownedPagesCursor;
47
48 public TableScanCursor(TableImpl table) {
49 super(new IdImpl(table, null), table,
50 FIRST_SCAN_POSITION, LAST_SCAN_POSITION);
51 _ownedPagesCursor = table.getOwnedPagesCursor();
52 }
53
54 @Override
55 protected ScanDirHandler getDirHandler(boolean moveForward) {
56 return (moveForward ? _forwardDirHandler : _reverseDirHandler);
57 }
58
59 @Override
60 protected boolean isUpToDate() {
61 return(super.isUpToDate() && _ownedPagesCursor.isUpToDate());
62 }
63
64 @Override
65 protected void reset(boolean moveForward) {
66 _ownedPagesCursor.reset(moveForward);
67 super.reset(moveForward);
68 }
69
70 @Override
71 protected void restorePositionImpl(PositionImpl curPos, PositionImpl prevPos)
72 throws IOException
73 {
74 if(!(curPos instanceof ScanPosition) ||
75 !(prevPos instanceof ScanPosition)) {
76 throw new IllegalArgumentException(
77 "Restored positions must be scan positions");
78 }
79 _ownedPagesCursor.restorePosition(curPos.getRowId().getPageNumber(),
80 prevPos.getRowId().getPageNumber());
81 super.restorePositionImpl(curPos, prevPos);
82 }
83
84 @Override
85 protected PositionImpl getRowPosition(RowIdImpl rowId) throws IOException
86 {
87 return new ScanPosition(rowId);
88 }
89
90 @Override
91 protected PositionImpl findAnotherPosition(
92 RowState rowState, PositionImpl curPos, boolean moveForward)
93 throws IOException
94 {
95 ScanDirHandler handler = getDirHandler(moveForward);
96
97
98
99 RowIdImpl curRowId = curPos.getRowId();
100 TableImpl.positionAtRowHeader(rowState, curRowId);
101 int currentRowNumber = curRowId.getRowNumber();
102
103
104 while(true) {
105
106 currentRowNumber = handler.getAnotherRowNumber(currentRowNumber);
107 curRowId = new RowIdImpl(curRowId.getPageNumber(), currentRowNumber);
108 TableImpl.positionAtRowHeader(rowState, curRowId);
109
110 if(!rowState.isValid()) {
111
112
113 curRowId = new RowIdImpl(handler.getAnotherPageNumber(),
114 RowIdImpl.INVALID_ROW_NUMBER);
115 TableImpl.positionAtRowHeader(rowState, curRowId);
116
117 if(!rowState.isHeaderPageNumberValid()) {
118
119 return handler.getEndPosition();
120 }
121
122
123 currentRowNumber = handler.getInitialRowNumber(
124 rowState.getRowsOnHeaderPage());
125
126 } else if(!rowState.isDeleted()) {
127
128
129 return new ScanPosition(curRowId);
130 }
131
132 }
133 }
134
135
136
137
138
139 private abstract class ScanDirHandler extends DirHandler {
140 public abstract int getAnotherRowNumber(int curRowNumber);
141 public abstract int getAnotherPageNumber();
142 public abstract int getInitialRowNumber(int rowsOnPage);
143 }
144
145
146
147
148 private final class ForwardScanDirHandler extends ScanDirHandler {
149 @Override
150 public PositionImpl getBeginningPosition() {
151 return getFirstPosition();
152 }
153 @Override
154 public PositionImpl getEndPosition() {
155 return getLastPosition();
156 }
157 @Override
158 public int getAnotherRowNumber(int curRowNumber) {
159 return curRowNumber + 1;
160 }
161 @Override
162 public int getAnotherPageNumber() {
163 return _ownedPagesCursor.getNextPage();
164 }
165 @Override
166 public int getInitialRowNumber(int rowsOnPage) {
167 return -1;
168 }
169 }
170
171
172
173
174 private final class ReverseScanDirHandler extends ScanDirHandler {
175 @Override
176 public PositionImpl getBeginningPosition() {
177 return getLastPosition();
178 }
179 @Override
180 public PositionImpl getEndPosition() {
181 return getFirstPosition();
182 }
183 @Override
184 public int getAnotherRowNumber(int curRowNumber) {
185 return curRowNumber - 1;
186 }
187 @Override
188 public int getAnotherPageNumber() {
189 return _ownedPagesCursor.getPreviousPage();
190 }
191 @Override
192 public int getInitialRowNumber(int rowsOnPage) {
193 return rowsOnPage;
194 }
195 }
196
197
198
199
200 private static final class ScanPosition extends PositionImpl
201 {
202 private final RowIdImpl _rowId;
203
204 private ScanPosition(RowIdImpl rowId) {
205 _rowId = rowId;
206 }
207
208 @Override
209 public RowIdImpl getRowId() {
210 return _rowId;
211 }
212
213 @Override
214 protected boolean equalsImpl(Object o) {
215 return getRowId().equals(((ScanPosition)o).getRowId());
216 }
217
218 @Override
219 public String toString() {
220 return "RowId = " + getRowId();
221 }
222 }
223 }