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