/*- * See the file LICENSE for redistribution information. * * Copyright (c) 2002, 2015 Oracle and/or its affiliates. All rights reserved. * */ package com.sleepycat.persist; import java.util.Iterator; import com.sleepycat.db.DatabaseEntry; import com.sleepycat.db.DatabaseException; import com.sleepycat.db.LockMode; import com.sleepycat.db.OperationStatus; import com.sleepycat.util.keyrange.RangeCursor; /** * Implements EntityCursor and uses a ValueAdapter so that it can enumerate * either keys or entities. * * @author Mark Hayes */ class BasicCursor<V> implements EntityCursor<V> { RangeCursor cursor; ValueAdapter<V> adapter; boolean updateAllowed; DatabaseEntry key; DatabaseEntry pkey; DatabaseEntry data; BasicCursor(RangeCursor cursor, ValueAdapter<V> adapter, boolean updateAllowed) { this.cursor = cursor; this.adapter = adapter; this.updateAllowed = updateAllowed; key = adapter.initKey(); pkey = adapter.initPKey(); data = adapter.initData(); } public V first() throws DatabaseException { return first(null); } public V first(LockMode lockMode) throws DatabaseException { return returnValue(cursor.getFirst(key, pkey, data, lockMode)); } public V last() throws DatabaseException { return last(null); } public V last(LockMode lockMode) throws DatabaseException { return returnValue(cursor.getLast(key, pkey, data, lockMode)); } public V next() throws DatabaseException { return next(null); } public V next(LockMode lockMode) throws DatabaseException { return returnValue(cursor.getNext(key, pkey, data, lockMode)); } public V nextDup() throws DatabaseException { return nextDup(null); } public V nextDup(LockMode lockMode) throws DatabaseException { checkInitialized(); return returnValue(cursor.getNextDup(key, pkey, data, lockMode)); } public V nextNoDup() throws DatabaseException { return nextNoDup(null); } public V nextNoDup(LockMode lockMode) throws DatabaseException { return returnValue(cursor.getNextNoDup(key, pkey, data, lockMode)); } public V prev() throws DatabaseException { return prev(null); } public V prev(LockMode lockMode) throws DatabaseException { return returnValue(cursor.getPrev(key, pkey, data, lockMode)); } public V prevDup() throws DatabaseException { return prevDup(null); } public V prevDup(LockMode lockMode) throws DatabaseException { checkInitialized(); return returnValue(cursor.getPrevDup(key, pkey, data, lockMode)); } public V prevNoDup() throws DatabaseException { return prevNoDup(null); } public V prevNoDup(LockMode lockMode) throws DatabaseException { return returnValue(cursor.getPrevNoDup(key, pkey, data, lockMode)); } public V current() throws DatabaseException { return current(null); } public V current(LockMode lockMode) throws DatabaseException { checkInitialized(); return returnValue(cursor.getCurrent(key, pkey, data, lockMode)); } public int count() throws DatabaseException { checkInitialized(); return cursor.count(); } public Iterator<V> iterator() { return iterator(null); } public Iterator<V> iterator(LockMode lockMode) { return new BasicIterator(this, lockMode); } public boolean update(V entity) throws DatabaseException { if (!updateAllowed) { throw new UnsupportedOperationException ("Update not allowed on a secondary index"); } checkInitialized(); adapter.valueToData(entity, data); return cursor.putCurrent(data) == OperationStatus.SUCCESS; } public boolean delete() throws DatabaseException { checkInitialized(); return cursor.delete() == OperationStatus.SUCCESS; } public EntityCursor<V> dup() throws DatabaseException { return new BasicCursor<V>(cursor.dup(true), adapter, updateAllowed); } public void close() throws DatabaseException { cursor.close(); } void checkInitialized() throws IllegalStateException { if (!cursor.isInitialized()) { throw new IllegalStateException ("Cursor is not initialized at a valid position"); } } V returnValue(OperationStatus status) { V value; if (status == OperationStatus.SUCCESS) { value = adapter.entryToValue(key, pkey, data); } else { value = null; } /* Clear entries to save memory. */ adapter.clearEntries(key, pkey, data); return value; } }