1/*- 2 * See the file LICENSE for redistribution information. 3 * 4 * Copyright (c) 2002,2008 Oracle. All rights reserved. 5 * 6 * $Id: BasicCursor.java,v 1.1 2008/02/07 17:12:26 mark Exp $ 7 */ 8 9package com.sleepycat.persist; 10 11import java.util.Iterator; 12 13import com.sleepycat.db.DatabaseEntry; 14import com.sleepycat.db.DatabaseException; 15import com.sleepycat.db.LockMode; 16import com.sleepycat.db.OperationStatus; 17import com.sleepycat.util.keyrange.RangeCursor; 18 19/** 20 * Implements EntityCursor and uses a ValueAdapter so that it can enumerate 21 * either keys or entities. 22 * 23 * @author Mark Hayes 24 */ 25class BasicCursor<V> implements EntityCursor<V> { 26 27 RangeCursor cursor; 28 ValueAdapter<V> adapter; 29 boolean updateAllowed; 30 DatabaseEntry key; 31 DatabaseEntry pkey; 32 DatabaseEntry data; 33 34 BasicCursor(RangeCursor cursor, 35 ValueAdapter<V> adapter, 36 boolean updateAllowed) { 37 this.cursor = cursor; 38 this.adapter = adapter; 39 this.updateAllowed = updateAllowed; 40 key = adapter.initKey(); 41 pkey = adapter.initPKey(); 42 data = adapter.initData(); 43 } 44 45 public V first() 46 throws DatabaseException { 47 48 return first(null); 49 } 50 51 public V first(LockMode lockMode) 52 throws DatabaseException { 53 54 return returnValue(cursor.getFirst(key, pkey, data, lockMode)); 55 } 56 57 public V last() 58 throws DatabaseException { 59 60 return last(null); 61 } 62 63 public V last(LockMode lockMode) 64 throws DatabaseException { 65 66 return returnValue(cursor.getLast(key, pkey, data, lockMode)); 67 } 68 69 public V next() 70 throws DatabaseException { 71 72 return next(null); 73 } 74 75 public V next(LockMode lockMode) 76 throws DatabaseException { 77 78 return returnValue(cursor.getNext(key, pkey, data, lockMode)); 79 } 80 81 public V nextDup() 82 throws DatabaseException { 83 84 return nextDup(null); 85 } 86 87 public V nextDup(LockMode lockMode) 88 throws DatabaseException { 89 90 checkInitialized(); 91 return returnValue(cursor.getNextDup(key, pkey, data, lockMode)); 92 } 93 94 public V nextNoDup() 95 throws DatabaseException { 96 97 return nextNoDup(null); 98 } 99 100 public V nextNoDup(LockMode lockMode) 101 throws DatabaseException { 102 103 return returnValue(cursor.getNextNoDup(key, pkey, data, lockMode)); 104 } 105 106 public V prev() 107 throws DatabaseException { 108 109 return prev(null); 110 } 111 112 public V prev(LockMode lockMode) 113 throws DatabaseException { 114 115 return returnValue(cursor.getPrev(key, pkey, data, lockMode)); 116 } 117 118 public V prevDup() 119 throws DatabaseException { 120 121 return prevDup(null); 122 } 123 124 public V prevDup(LockMode lockMode) 125 throws DatabaseException { 126 127 checkInitialized(); 128 return returnValue(cursor.getPrevDup(key, pkey, data, lockMode)); 129 } 130 131 public V prevNoDup() 132 throws DatabaseException { 133 134 return prevNoDup(null); 135 } 136 137 public V prevNoDup(LockMode lockMode) 138 throws DatabaseException { 139 140 return returnValue(cursor.getPrevNoDup(key, pkey, data, lockMode)); 141 } 142 143 public V current() 144 throws DatabaseException { 145 146 return current(null); 147 } 148 149 public V current(LockMode lockMode) 150 throws DatabaseException { 151 152 checkInitialized(); 153 return returnValue(cursor.getCurrent(key, pkey, data, lockMode)); 154 } 155 156 public int count() 157 throws DatabaseException { 158 159 checkInitialized(); 160 return cursor.count(); 161 } 162 163 public Iterator<V> iterator() { 164 return iterator(null); 165 } 166 167 public Iterator<V> iterator(LockMode lockMode) { 168 return new BasicIterator(this, lockMode); 169 } 170 171 public boolean update(V entity) 172 throws DatabaseException { 173 174 if (!updateAllowed) { 175 throw new UnsupportedOperationException 176 ("Update not allowed on a secondary index"); 177 } 178 checkInitialized(); 179 adapter.valueToData(entity, data); 180 return cursor.putCurrent(data) == OperationStatus.SUCCESS; 181 } 182 183 public boolean delete() 184 throws DatabaseException { 185 186 checkInitialized(); 187 return cursor.delete() == OperationStatus.SUCCESS; 188 } 189 190 public EntityCursor<V> dup() 191 throws DatabaseException { 192 193 return new BasicCursor<V>(cursor.dup(true), adapter, updateAllowed); 194 } 195 196 public void close() 197 throws DatabaseException { 198 199 cursor.close(); 200 } 201 202 void checkInitialized() 203 throws IllegalStateException { 204 205 if (!cursor.isInitialized()) { 206 throw new IllegalStateException 207 ("Cursor is not initialized at a valid position"); 208 } 209 } 210 211 V returnValue(OperationStatus status) { 212 V value; 213 if (status == OperationStatus.SUCCESS) { 214 value = adapter.entryToValue(key, pkey, data); 215 } else { 216 value = null; 217 } 218 /* Clear entries to save memory. */ 219 adapter.clearEntries(key, pkey, data); 220 return value; 221 } 222} 223