/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package com.github.geophile.erdo.map.keyarray;
import com.github.geophile.erdo.AbstractKey;
import com.github.geophile.erdo.AbstractRecord;
import com.github.geophile.erdo.map.KeyOnlyRecord;
import com.github.geophile.erdo.map.MapCursor;
public class KeyArrayCursor extends MapCursor
{
// MapCursor interface
public AbstractRecord next()
{
return neighbor(true);
}
@Override
public AbstractRecord previous()
{
return neighbor(false);
}
public void close()
{
if (state != State.DONE) {
current = keys.size();
keys = null;
super.close();
}
}
// KeyArrayCursor interface
KeyArrayCursor(KeyArray keys, AbstractKey startKey)
{
super(startKey, false);
this.keys = keys;
}
// For use by this class
private AbstractRecord neighbor(boolean forward)
{
AbstractKey next = null;
switch (state) {
case NEVER_USED:
if (startKey == null) {
current = forward ? 0 : keys.size() - 1;
} else {
current = keys.binarySearch(startKey);
if (current < 0) {
current =
forward
? -current - 1
: -current - 2;
}
}
state = State.IN_USE;
break;
case IN_USE:
if (forward) {
current++;
} else {
current--;
}
break;
case DONE:
return null;
}
if (current >= 0 && current < keys.size()) {
// Why null is passed to keys.key: We could have currentKey be a field, and then reuse the
// key. But we're returning a KeyOnlyRecord containing a key. If multiple KeyOnlyRecords
// wrap the same AbstractKey object, that's bad. null forces allocation of a new key.
AbstractKey currentKey = keys.key(current, null);
if (isOpen(currentKey)) {
next = currentKey;
} else {
close();
}
} else {
close();
}
return next == null ? null : new KeyOnlyRecord(next);
}
// Object state
private KeyArray keys;
private int current;
}