Skip to content

Commit 3a5c6db

Browse files
committed
Move control logic from KeyRange to KeyRangeTest (#7)
This simplifies KeyRange, which is the user-facing class. It also colocates the control logic with the detailed descriptions and examples of what each KeyRangeType is supposed to do, making it easier to understand and maintain.
1 parent 7881199 commit 3a5c6db

File tree

4 files changed

+164
-157
lines changed

4 files changed

+164
-157
lines changed

src/main/java/org/lmdbjava/CursorIterator.java

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@
2929
import static org.lmdbjava.CursorIterator.State.REQUIRES_NEXT_OP;
3030
import static org.lmdbjava.CursorIterator.State.TERMINATED;
3131
import static org.lmdbjava.GetOp.MDB_SET_RANGE;
32-
import org.lmdbjava.KeyRange.CursorOp;
33-
import org.lmdbjava.KeyRange.IteratorOp;
32+
import org.lmdbjava.KeyRangeType.CursorOp;
33+
import org.lmdbjava.KeyRangeType.IteratorOp;
3434

3535
/**
3636
* {@link Iterator} that iterates over a {@link Cursor} as specified by a
@@ -121,10 +121,12 @@ private void executeCursorOp(final CursorOp op) {
121121
}
122122

123123
private void executeIteratorOp() {
124-
final IteratorOp op = range.iteratorOp(comparator, entry.key());
124+
final IteratorOp op = range.getType().iteratorOp(range.getStart(),
125+
range.getStop(),
126+
entry.key(), comparator);
125127
switch (op) {
126128
case CALL_NEXT_OP:
127-
executeCursorOp(range.nextOp());
129+
executeCursorOp(range.getType().nextOp());
128130
state = REQUIRES_ITERATOR_OP;
129131
break;
130132
case TERMINATE:
@@ -141,11 +143,11 @@ private void executeIteratorOp() {
141143
private void update() {
142144
switch (state) {
143145
case REQUIRES_INITIAL_OP:
144-
executeCursorOp(range.initialOp());
146+
executeCursorOp(range.getType().initialOp());
145147
state = REQUIRES_ITERATOR_OP;
146148
break;
147149
case REQUIRES_NEXT_OP:
148-
executeCursorOp(range.nextOp());
150+
executeCursorOp(range.getType().nextOp());
149151
state = REQUIRES_ITERATOR_OP;
150152
break;
151153
case REQUIRES_ITERATOR_OP:

src/main/java/org/lmdbjava/KeyRange.java

Lines changed: 0 additions & 141 deletions
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,7 @@
2020

2121
package org.lmdbjava;
2222

23-
import java.util.Comparator;
2423
import static java.util.Objects.requireNonNull;
25-
import static org.lmdbjava.KeyRange.CursorOp.FIRST;
26-
import static org.lmdbjava.KeyRange.CursorOp.GET_START_KEY;
27-
import static org.lmdbjava.KeyRange.CursorOp.LAST;
28-
import static org.lmdbjava.KeyRange.CursorOp.NEXT;
29-
import static org.lmdbjava.KeyRange.CursorOp.PREV;
30-
import static org.lmdbjava.KeyRange.IteratorOp.CALL_NEXT_OP;
31-
import static org.lmdbjava.KeyRange.IteratorOp.RELEASE;
32-
import static org.lmdbjava.KeyRange.IteratorOp.TERMINATE;
3324
import static org.lmdbjava.KeyRangeType.BACKWARD_ALL;
3425
import static org.lmdbjava.KeyRangeType.FORWARD_ALL;
3526

@@ -41,7 +32,6 @@
4132
*
4233
* @param <T> buffer type
4334
*/
44-
@SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.StdCyclomaticComplexity"})
4535
public final class KeyRange<T> {
4636

4737
private static final KeyRange BACK = new KeyRange<>(BACKWARD_ALL, null, null);
@@ -189,135 +179,4 @@ public KeyRangeType getType() {
189179
return type;
190180
}
191181

192-
/**
193-
* Determine the iterator action to take when iterator first begins.
194-
*
195-
* <p>
196-
* The iterator will perform this action and present the resulting key to
197-
* {@link #iteratorOp(java.util.Comparator, java.lang.Object)} for decision.
198-
*
199-
* @return appropriate action in response to this buffer
200-
*/
201-
@SuppressWarnings("checkstyle:ReturnCount")
202-
CursorOp initialOp() {
203-
switch (type) {
204-
case FORWARD_ALL:
205-
return FIRST;
206-
case FORWARD_AT_LEAST:
207-
return GET_START_KEY;
208-
case FORWARD_AT_MOST:
209-
return FIRST;
210-
case FORWARD_CLOSED:
211-
return GET_START_KEY;
212-
case BACKWARD_ALL:
213-
return LAST;
214-
case BACKWARD_AT_LEAST:
215-
return GET_START_KEY;
216-
case BACKWARD_AT_MOST:
217-
return LAST;
218-
case BACKWARD_CLOSED:
219-
return GET_START_KEY;
220-
default:
221-
throw new IllegalStateException("Invalid type");
222-
}
223-
}
224-
225-
/**
226-
* Determine the iterator's response to the presented key.
227-
*
228-
* @param <C> comparator for the buffers
229-
* @param c comparator (required)
230-
* @param buffer current key returned by LMDB (may be null)
231-
* @return response to this key
232-
*/
233-
@SuppressWarnings("checkstyle:ReturnCount")
234-
<C extends Comparator<T>> IteratorOp iteratorOp(final C c,
235-
final T buffer) {
236-
requireNonNull(c, "Comparator required");
237-
if (buffer == null) {
238-
return TERMINATE;
239-
}
240-
switch (type) {
241-
case FORWARD_ALL:
242-
return RELEASE;
243-
case FORWARD_AT_LEAST:
244-
return RELEASE;
245-
case FORWARD_AT_MOST:
246-
return c.compare(buffer, stop) > 0 ? TERMINATE : RELEASE;
247-
case FORWARD_CLOSED:
248-
return c.compare(buffer, stop) > 0 ? TERMINATE : RELEASE;
249-
case BACKWARD_ALL:
250-
return RELEASE;
251-
case BACKWARD_AT_LEAST:
252-
return c.compare(buffer, start) > 0 ? CALL_NEXT_OP : RELEASE; // rewind
253-
case BACKWARD_AT_MOST:
254-
return c.compare(buffer, stop) >= 0 ? RELEASE : TERMINATE;
255-
case BACKWARD_CLOSED:
256-
if (c.compare(buffer, start) > 0) {
257-
return CALL_NEXT_OP; // rewind
258-
}
259-
return c.compare(buffer, stop) >= 0 ? RELEASE : TERMINATE;
260-
default:
261-
throw new IllegalStateException("Invalid type");
262-
}
263-
}
264-
265-
/**
266-
* Determine the iterator action to take when "next" is called or upon request
267-
* of {@link #iteratorOp(java.util.Comparator, java.lang.Object)}.
268-
*
269-
* <p>
270-
* The iterator will perform this action and present the resulting key to
271-
* {@link #iteratorOp(java.util.Comparator, java.lang.Object)} for decision.
272-
*
273-
* @return appropriate action for this key range type
274-
*/
275-
CursorOp nextOp() {
276-
return type.isDirectionForward() ? NEXT : PREV;
277-
}
278-
279-
/**
280-
* Action now required with the iterator.
281-
*/
282-
enum IteratorOp {
283-
/**
284-
* Consider iterator completed.
285-
*/
286-
TERMINATE,
287-
/**
288-
* Call {@link KeyRange#nextOp()} again and try again.
289-
*/
290-
CALL_NEXT_OP,
291-
/**
292-
* Return the key to the user.
293-
*/
294-
RELEASE
295-
}
296-
297-
/**
298-
* Action now required with the cursor.
299-
*/
300-
enum CursorOp {
301-
/**
302-
* Move to first.
303-
*/
304-
FIRST,
305-
/**
306-
* Move to last.
307-
*/
308-
LAST,
309-
/**
310-
* Get "start" key with {@link GetOp#MDB_SET_RANGE}.
311-
*/
312-
GET_START_KEY,
313-
/**
314-
* Move forward.
315-
*/
316-
NEXT,
317-
/**
318-
* Move backward.
319-
*/
320-
PREV
321-
}
322-
323182
}

src/main/java/org/lmdbjava/KeyRangeType.java

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,19 @@
2020

2121
package org.lmdbjava;
2222

23+
import java.util.Comparator;
24+
import static java.util.Objects.requireNonNull;
25+
import static org.lmdbjava.KeyRangeType.BACKWARD_ALL;
26+
import static org.lmdbjava.KeyRangeType.CursorOp.FIRST;
27+
import static org.lmdbjava.KeyRangeType.CursorOp.GET_START_KEY;
28+
import static org.lmdbjava.KeyRangeType.CursorOp.LAST;
29+
import static org.lmdbjava.KeyRangeType.CursorOp.NEXT;
30+
import static org.lmdbjava.KeyRangeType.CursorOp.PREV;
31+
import static org.lmdbjava.KeyRangeType.FORWARD_ALL;
32+
import static org.lmdbjava.KeyRangeType.IteratorOp.CALL_NEXT_OP;
33+
import static org.lmdbjava.KeyRangeType.IteratorOp.RELEASE;
34+
import static org.lmdbjava.KeyRangeType.IteratorOp.TERMINATE;
35+
2336
/**
2437
* Key range type.
2538
*
@@ -32,6 +45,7 @@
3245
* <p>
3346
* In the examples below, it is assumed the table has keys 2, 4, 6 and 8.
3447
*/
48+
@SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.StdCyclomaticComplexity"})
3549
public enum KeyRangeType {
3650

3751
/**
@@ -169,4 +183,137 @@ public boolean isStopKeyRequired() {
169183
return stopKeyRequired;
170184
}
171185

186+
/**
187+
* Determine the iterator action to take when iterator first begins.
188+
*
189+
* <p>
190+
* The iterator will perform this action and present the resulting key to
191+
* {@link #iteratorOp(java.util.Comparator, java.lang.Object)} for decision.
192+
*
193+
* @return appropriate action in response to this buffer
194+
*/
195+
@SuppressWarnings("checkstyle:ReturnCount")
196+
CursorOp initialOp() {
197+
switch (this) {
198+
case FORWARD_ALL:
199+
return FIRST;
200+
case FORWARD_AT_LEAST:
201+
return GET_START_KEY;
202+
case FORWARD_AT_MOST:
203+
return FIRST;
204+
case FORWARD_CLOSED:
205+
return GET_START_KEY;
206+
case BACKWARD_ALL:
207+
return LAST;
208+
case BACKWARD_AT_LEAST:
209+
return GET_START_KEY;
210+
case BACKWARD_AT_MOST:
211+
return LAST;
212+
case BACKWARD_CLOSED:
213+
return GET_START_KEY;
214+
default:
215+
throw new IllegalStateException("Invalid type");
216+
}
217+
}
218+
219+
/**
220+
* Determine the iterator's response to the presented key.
221+
*
222+
* @param <T> buffer type
223+
* @param <C> comparator for the buffers
224+
* @param start start buffer
225+
* @param stop stop buffer
226+
* @param buffer current key returned by LMDB (may be null)
227+
* @param c comparator (required)
228+
* @return response to this key
229+
*/
230+
@SuppressWarnings("checkstyle:ReturnCount")
231+
<T, C extends Comparator<T>> IteratorOp iteratorOp(final T start, final T stop,
232+
final T buffer, final C c) {
233+
requireNonNull(c, "Comparator required");
234+
if (buffer == null) {
235+
return TERMINATE;
236+
}
237+
switch (this) {
238+
case FORWARD_ALL:
239+
return RELEASE;
240+
case FORWARD_AT_LEAST:
241+
return RELEASE;
242+
case FORWARD_AT_MOST:
243+
return c.compare(buffer, stop) > 0 ? TERMINATE : RELEASE;
244+
case FORWARD_CLOSED:
245+
return c.compare(buffer, stop) > 0 ? TERMINATE : RELEASE;
246+
case BACKWARD_ALL:
247+
return RELEASE;
248+
case BACKWARD_AT_LEAST:
249+
return c.compare(buffer, start) > 0 ? CALL_NEXT_OP : RELEASE; // rewind
250+
case BACKWARD_AT_MOST:
251+
return c.compare(buffer, stop) >= 0 ? RELEASE : TERMINATE;
252+
case BACKWARD_CLOSED:
253+
if (c.compare(buffer, start) > 0) {
254+
return CALL_NEXT_OP; // rewind
255+
}
256+
return c.compare(buffer, stop) >= 0 ? RELEASE : TERMINATE;
257+
default:
258+
throw new IllegalStateException("Invalid type");
259+
}
260+
}
261+
262+
/**
263+
* Determine the iterator action to take when "next" is called or upon request
264+
* of {@link #iteratorOp(java.util.Comparator, java.lang.Object)}.
265+
*
266+
* <p>
267+
* The iterator will perform this action and present the resulting key to
268+
* {@link #iteratorOp(java.util.Comparator, java.lang.Object)} for decision.
269+
*
270+
* @return appropriate action for this key range type
271+
*/
272+
CursorOp nextOp() {
273+
return isDirectionForward() ? NEXT : PREV;
274+
}
275+
276+
/**
277+
* Action now required with the iterator.
278+
*/
279+
enum IteratorOp {
280+
/**
281+
* Consider iterator completed.
282+
*/
283+
TERMINATE,
284+
/**
285+
* Call {@link KeyRange#nextOp()} again and try again.
286+
*/
287+
CALL_NEXT_OP,
288+
/**
289+
* Return the key to the user.
290+
*/
291+
RELEASE
292+
}
293+
294+
/**
295+
* Action now required with the cursor.
296+
*/
297+
enum CursorOp {
298+
/**
299+
* Move to first.
300+
*/
301+
FIRST,
302+
/**
303+
* Move to last.
304+
*/
305+
LAST,
306+
/**
307+
* Get "start" key with {@link GetOp#MDB_SET_RANGE}.
308+
*/
309+
GET_START_KEY,
310+
/**
311+
* Move forward.
312+
*/
313+
NEXT,
314+
/**
315+
* Move backward.
316+
*/
317+
PREV
318+
}
172319
}

0 commit comments

Comments
 (0)