Source Code Cross Referenced for StoredIterator.java in  » JMX » je » com » sleepycat » collections » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » JMX » je » com.sleepycat.collections 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*-
002:         * See the file LICENSE for redistribution information.
003:         *
004:         * Copyright (c) 2000,2008 Oracle.  All rights reserved.
005:         *
006:         * $Id: StoredIterator.java,v 1.45.2.5 2008/01/07 15:14:06 cwl Exp $
007:         */
008:
009:        package com.sleepycat.collections;
010:
011:        import java.util.Iterator;
012:        import java.util.ListIterator;
013:        import java.util.NoSuchElementException;
014:
015:        import com.sleepycat.je.DatabaseException;
016:        import com.sleepycat.je.OperationStatus;
017:        import com.sleepycat.util.RuntimeExceptionWrapper;
018:
019:        /**
020:         * The Iterator returned by all stored collections.
021:         *
022:         * <p>While in general this class conforms to the {@link Iterator} interface,
023:         * it is important to note that all iterators for stored collections must be
024:         * explicitly closed with {@link #close()}.  The static method {@link
025:         * #close(java.util.Iterator)} allows calling close for all iterators without
026:         * harm to iterators that are not from stored collections, and also avoids
027:         * casting.  If a stored iterator is not closed, unpredictable behavior
028:         * including process death may result.</p>
029:         *
030:         * <p>This class implements the {@link Iterator} interface for all stored
031:         * iterators.  It also implements {@link ListIterator} because some list
032:         * iterator methods apply to all stored iterators, for example, {@link
033:         * #previous} and {@link #hasPrevious}.  Other list iterator methods are always
034:         * supported for lists, but for other types of collections are only supported
035:         * under certain conditions.  See {@link #nextIndex}, {@link #previousIndex},
036:         * {@link #add} and {@link #set} for details.</p>
037:         *
038:         * <p>In addition, this class provides the following methods for stored
039:         * collection iterators only.  Note that the use of these methods is not
040:         * compatible with the standard Java collections interface.</p>
041:         * <ul>
042:         * <li>{@link #close()}</li>
043:         * <li>{@link #close(Iterator)}</li>
044:         * <li>{@link #count()}</li>
045:         * <li>{@link #getCollection}</li>
046:         * <li>{@link #setReadModifyWrite}</li>
047:         * <li>{@link #isReadModifyWrite}</li>
048:         * </ul>
049:         *
050:         * @author Mark Hayes
051:         */
052:        public class StoredIterator implements  BaseIterator, Cloneable {
053:
054:            /**
055:             * Closes the given iterator using {@link #close()} if it is a {@link
056:             * StoredIterator}.  If the given iterator is not a {@link StoredIterator},
057:             * this method does nothing.
058:             *
059:             * @param i is the iterator to close.
060:             *
061:             * @throws RuntimeExceptionWrapper if a {@link DatabaseException} is thrown.
062:             */
063:            public static void close(Iterator i) {
064:
065:                if (i instanceof  StoredIterator) {
066:                    ((StoredIterator) i).close();
067:                }
068:            }
069:
070:            private static final int MOVE_NEXT = 1;
071:            private static final int MOVE_PREV = 2;
072:            private static final int MOVE_FIRST = 3;
073:
074:            private boolean lockForWrite;
075:            private StoredCollection coll;
076:            private DataCursor cursor;
077:            private int toNext;
078:            private int toPrevious;
079:            private int toCurrent;
080:            private boolean writeAllowed;
081:            private boolean setAndRemoveAllowed;
082:            private Object currentData;
083:
084:            StoredIterator(StoredCollection coll, boolean writeAllowed,
085:                    DataCursor joinCursor) {
086:                try {
087:                    this .coll = coll;
088:                    this .writeAllowed = writeAllowed;
089:                    if (joinCursor == null)
090:                        this .cursor = new DataCursor(coll.view, writeAllowed);
091:                    else
092:                        this .cursor = joinCursor;
093:                    reset();
094:                } catch (Exception e) {
095:                    try {
096:                        /* Ensure that the cursor is closed.  [#10516] */
097:                        close();
098:                    } catch (Exception ignored) {
099:                        /* Klockwork - ok */
100:                    }
101:                    throw StoredContainer.convertException(e);
102:                }
103:            }
104:
105:            /**
106:             * Returns whether write-locks will be obtained when reading with this
107:             * cursor.
108:             * Obtaining write-locks can prevent deadlocks when reading and then
109:             * modifying data.
110:             *
111:             * @return the write-lock setting.
112:             */
113:            public final boolean isReadModifyWrite() {
114:
115:                return lockForWrite;
116:            }
117:
118:            /**
119:             * Changes whether write-locks will be obtained when reading with this
120:             * cursor.
121:             * Obtaining write-locks can prevent deadlocks when reading and then
122:             * modifying data.
123:             *
124:             * @param lockForWrite the write-lock setting.
125:             */
126:            public void setReadModifyWrite(boolean lockForWrite) {
127:
128:                this .lockForWrite = lockForWrite;
129:            }
130:
131:            // --- begin Iterator/ListIterator methods ---
132:
133:            /**
134:             * Returns true if this iterator has more elements when traversing in the
135:             * forward direction.  False is returned if the iterator has been closed.
136:             * This method conforms to the {@link Iterator#hasNext} interface.
137:             *
138:             * @return whether {@link #next()} will succeed.
139:             *
140:             * @throws RuntimeExceptionWrapper if a {@link DatabaseException} is thrown.
141:             */
142:            public boolean hasNext() {
143:
144:                if (cursor == null) {
145:                    return false;
146:                }
147:                try {
148:                    if (toNext != 0) {
149:                        OperationStatus status = move(toNext);
150:                        if (status == OperationStatus.SUCCESS) {
151:                            toNext = 0;
152:                            toPrevious = MOVE_PREV;
153:                            toCurrent = MOVE_PREV;
154:                        }
155:                    }
156:                    return (toNext == 0);
157:                } catch (Exception e) {
158:                    throw StoredContainer.convertException(e);
159:                }
160:            }
161:
162:            /**
163:             * Returns true if this iterator has more elements when traversing in the
164:             * reverse direction.  It returns false if the iterator has been closed.
165:             * This method conforms to the {@link ListIterator#hasPrevious} interface.
166:             *
167:             * @return whether {@link #previous()} will succeed.
168:             *
169:             * @throws RuntimeExceptionWrapper if a {@link DatabaseException} is thrown.
170:             */
171:            public boolean hasPrevious() {
172:
173:                if (cursor == null) {
174:                    return false;
175:                }
176:                try {
177:                    if (toPrevious != 0) {
178:                        OperationStatus status = move(toPrevious);
179:                        if (status == OperationStatus.SUCCESS) {
180:                            toPrevious = 0;
181:                            toNext = MOVE_NEXT;
182:                            toCurrent = MOVE_NEXT;
183:                        }
184:                    }
185:                    return (toPrevious == 0);
186:                } catch (Exception e) {
187:                    throw StoredContainer.convertException(e);
188:                }
189:            }
190:
191:            /**
192:             * Returns the next element in the iteration.
193:             * This method conforms to the {@link Iterator#next} interface.
194:             *
195:             * @return the next element.
196:             *
197:             * @throws RuntimeExceptionWrapper if a {@link DatabaseException} is
198:             * thrown.
199:             */
200:            public Object next() {
201:
202:                try {
203:                    if (toNext != 0) {
204:                        OperationStatus status = move(toNext);
205:                        if (status == OperationStatus.SUCCESS) {
206:                            toNext = 0;
207:                        }
208:                    }
209:                    if (toNext == 0) {
210:                        currentData = coll.makeIteratorData(this , cursor);
211:                        toNext = MOVE_NEXT;
212:                        toPrevious = 0;
213:                        toCurrent = 0;
214:                        setAndRemoveAllowed = true;
215:                        return currentData;
216:                    }
217:                    // else throw NoSuchElementException below
218:                } catch (Exception e) {
219:                    throw StoredContainer.convertException(e);
220:                }
221:                throw new NoSuchElementException();
222:            }
223:
224:            /**
225:             * Returns the next element in the iteration.
226:             * This method conforms to the {@link ListIterator#previous} interface.
227:             *
228:             * @return the previous element.
229:             *
230:             * @throws RuntimeExceptionWrapper if a {@link DatabaseException} is
231:             * thrown.
232:             */
233:            public Object previous() {
234:
235:                try {
236:                    if (toPrevious != 0) {
237:                        OperationStatus status = move(toPrevious);
238:                        if (status == OperationStatus.SUCCESS) {
239:                            toPrevious = 0;
240:                        }
241:                    }
242:                    if (toPrevious == 0) {
243:                        currentData = coll.makeIteratorData(this , cursor);
244:                        toPrevious = MOVE_PREV;
245:                        toNext = 0;
246:                        toCurrent = 0;
247:                        setAndRemoveAllowed = true;
248:                        return currentData;
249:                    }
250:                    // else throw NoSuchElementException below
251:                } catch (Exception e) {
252:                    throw StoredContainer.convertException(e);
253:                }
254:                throw new NoSuchElementException();
255:            }
256:
257:            /**
258:             * Returns the index of the element that would be returned by a subsequent
259:             * call to next.
260:             * This method conforms to the {@link ListIterator#nextIndex} interface
261:             * except that it returns Integer.MAX_VALUE for stored lists when
262:             * positioned at the end of the list, rather than returning the list size
263:             * as specified by the ListIterator interface. This is because the database
264:             * size is not available.
265:             *
266:             * @return the next index.
267:             *
268:             * @throws UnsupportedOperationException if this iterator's collection does
269:             * not use record number keys.
270:             *
271:             * @throws RuntimeExceptionWrapper if a {@link DatabaseException} is
272:             * thrown.
273:             */
274:            public int nextIndex() {
275:
276:                if (!coll.view.recNumAccess) {
277:                    throw new UnsupportedOperationException(
278:                            "Record number access not supported");
279:                }
280:                try {
281:                    return hasNext() ? (cursor.getCurrentRecordNumber() - coll
282:                            .getIndexOffset()) : Integer.MAX_VALUE;
283:                } catch (Exception e) {
284:                    throw StoredContainer.convertException(e);
285:                }
286:            }
287:
288:            /**
289:             * Returns the index of the element that would be returned by a subsequent
290:             * call to previous.
291:             * This method conforms to the {@link ListIterator#previousIndex}
292:             * interface.
293:             *
294:             * @return the previous index.
295:             *
296:             * @throws UnsupportedOperationException if this iterator's collection does
297:             * not use record number keys.
298:             *
299:             * @throws RuntimeExceptionWrapper if a {@link DatabaseException} is
300:             * thrown.
301:             */
302:            public int previousIndex() {
303:
304:                if (!coll.view.recNumAccess) {
305:                    throw new UnsupportedOperationException(
306:                            "Record number access not supported");
307:                }
308:                try {
309:                    return hasPrevious() ? (cursor.getCurrentRecordNumber() - coll
310:                            .getIndexOffset())
311:                            : (-1);
312:                } catch (Exception e) {
313:                    throw StoredContainer.convertException(e);
314:                }
315:            }
316:
317:            /**
318:             * Replaces the last element returned by next or previous with the
319:             * specified element (optional operation).
320:             * This method conforms to the {@link ListIterator#set} interface.
321:             *
322:             * <p>In order to call this method, if the underlying Database is
323:             * transactional then a transaction must be active when creating the
324:             * iterator.</p>
325:             *
326:             * @param value the new value.
327:             *
328:             * @throws UnsupportedOperationException if the collection is a {@link
329:             * StoredKeySet} (the set returned by {@link java.util.Map#keySet}), or if
330:             * duplicates are sorted since this would change the iterator position, or
331:             * if the collection is indexed, or if the collection is read-only.
332:             *
333:             * @throws IllegalArgumentException if an entity value binding is used and
334:             * the primary key of the value given is different than the existing stored
335:             * primary key.
336:             *
337:             * @throws RuntimeExceptionWrapper if a {@link DatabaseException} is
338:             * thrown.
339:             */
340:            public void set(Object value) {
341:
342:                if (!coll.hasValues())
343:                    throw new UnsupportedOperationException();
344:                if (!setAndRemoveAllowed)
345:                    throw new IllegalStateException();
346:                try {
347:                    moveToCurrent();
348:                    cursor.putCurrent(value);
349:                } catch (Exception e) {
350:                    throw StoredContainer.convertException(e);
351:                }
352:            }
353:
354:            /**
355:             * Removes the last element that was returned by next or previous (optional
356:             * operation).
357:             * This method conforms to the {@link ListIterator#remove} interface except
358:             * that when the collection is a list and the RECNO-RENUMBER access method
359:             * is not used, list indices will not be renumbered.
360:             *
361:             * <p>In order to call this method, if the underlying Database is
362:             * transactional then a transaction must be active when creating the
363:             * iterator.</p>
364:             *
365:             * <p>Note that for the JE product, RECNO-RENUMBER databases are not
366:             * supported, and therefore list indices are never renumbered by this
367:             * method.</p>
368:             *
369:             * @throws UnsupportedOperationException if the collection is a sublist, or
370:             * if the collection is read-only.
371:             *
372:             * @throws RuntimeExceptionWrapper if a {@link DatabaseException} is
373:             * thrown.
374:             */
375:            public void remove() {
376:
377:                if (!setAndRemoveAllowed)
378:                    throw new IllegalStateException();
379:                try {
380:                    moveToCurrent();
381:                    cursor.delete();
382:                    setAndRemoveAllowed = false;
383:                    toNext = MOVE_NEXT;
384:                    toPrevious = MOVE_PREV;
385:                } catch (Exception e) {
386:                    throw StoredContainer.convertException(e);
387:                }
388:            }
389:
390:            /**
391:             * Inserts the specified element into the list or inserts a duplicate into
392:             * other types of collections (optional operation).
393:             * This method conforms to the {@link ListIterator#add} interface when
394:             * the collection is a list and the RECNO-RENUMBER access method is used.
395:             * Otherwise, this method may only be called when duplicates are allowed.
396:             * If duplicates are unsorted, the new value will be inserted in the same
397:             * manner as list elements.
398:             * If duplicates are sorted, the new value will be inserted in sort order.
399:             *
400:             * <p>Note that for the JE product, RECNO-RENUMBER databases are not
401:             * supported, and therefore this method may only be used to add
402:             * duplicates.</p>
403:             *
404:             * @param value the new value.
405:             *
406:             * @throws UnsupportedOperationException if the collection is a sublist, or
407:             * if the collection is indexed, or if the collection is read-only, or if
408:             * the collection is a list and the RECNO-RENUMBER access method was not
409:             * used, or if the collection is not a list and duplicates are not allowed.
410:             *
411:             * @throws IllegalStateException if the collection is empty and is not a
412:             * list with RECNO-RENUMBER access.
413:             *
414:             * @throws IllegalArgumentException if a duplicate value is being added
415:             * that already exists and duplicates are sorted.
416:             *
417:             * @throws RuntimeExceptionWrapper if a {@link DatabaseException} is
418:             * thrown.
419:             */
420:            public void add(Object value) {
421:
422:                coll.checkIterAddAllowed();
423:                try {
424:                    OperationStatus status = OperationStatus.SUCCESS;
425:                    if (toNext != 0 && toPrevious != 0) { // database is empty
426:                        if (coll.view.keysRenumbered) { // recno-renumber database
427:                            /*
428:                             * Close cursor during append and then reopen to support
429:                             * CDB restriction that append may not be called with a
430:                             * cursor open; note the append will still fail if the
431:                             * application has another cursor open.
432:                             */
433:                            close();
434:                            status = coll.view.append(value, null, null);
435:                            cursor = new DataCursor(coll.view, writeAllowed);
436:                            reset();
437:                            next(); // move past new record
438:                        } else { // hash/btree with duplicates
439:                            throw new IllegalStateException(
440:                                    "Collection is empty, cannot add() duplicate");
441:                        }
442:                    } else { // database is not empty
443:                        boolean putBefore = false;
444:                        if (coll.view.keysRenumbered) { // recno-renumber database
445:                            moveToCurrent();
446:                            if (hasNext()) {
447:                                status = cursor.putBefore(value);
448:                                putBefore = true;
449:                            } else {
450:                                status = cursor.putAfter(value);
451:                            }
452:                        } else { // hash/btree with duplicates
453:                            if (coll.areDuplicatesOrdered()) {
454:                                status = cursor.putNoDupData(null, value, null,
455:                                        true);
456:                            } else if (toNext == 0) {
457:                                status = cursor.putBefore(value);
458:                                putBefore = true;
459:                            } else {
460:                                status = cursor.putAfter(value);
461:                            }
462:                        }
463:                        if (putBefore) {
464:                            toPrevious = 0;
465:                            toNext = MOVE_NEXT;
466:                        }
467:                    }
468:                    if (status == OperationStatus.KEYEXIST) {
469:                        throw new IllegalArgumentException("Duplicate value");
470:                    } else if (status != OperationStatus.SUCCESS) {
471:                        throw new IllegalArgumentException("Could not insert: "
472:                                + status);
473:                    }
474:                    setAndRemoveAllowed = false;
475:                } catch (Exception e) {
476:                    throw StoredContainer.convertException(e);
477:                }
478:            }
479:
480:            // --- end Iterator/ListIterator methods ---
481:
482:            /**
483:             * Resets cursor to an uninitialized state.
484:             */
485:            private void reset() {
486:
487:                toNext = MOVE_FIRST;
488:                toPrevious = MOVE_PREV;
489:                toCurrent = 0;
490:                currentData = null;
491:                /*
492:                 * Initialize cursor at beginning to avoid "initial previous == last"
493:                 * behavior when cursor is uninitialized.
494:                 *
495:                 * FindBugs whines about us ignoring the return value from hasNext().
496:                 */
497:                hasNext();
498:            }
499:
500:            /**
501:             * Returns the number of elements having the same key value as the key
502:             * value of the element last returned by next() or previous().  If no
503:             * duplicates are allowed, 1 is always returned.
504:             * This method does not exist in the standard {@link Iterator} or {@link
505:             * ListIterator} interfaces.
506:             *
507:             * @return the number of duplicates.
508:             *
509:             * @throws IllegalStateException if next() or previous() has not been
510:             * called for this iterator, or if remove() or add() were called after
511:             * the last call to next() or previous().
512:             */
513:            public int count() {
514:
515:                if (!setAndRemoveAllowed)
516:                    throw new IllegalStateException();
517:                try {
518:                    moveToCurrent();
519:                    return cursor.count();
520:                } catch (Exception e) {
521:                    throw StoredContainer.convertException(e);
522:                }
523:            }
524:
525:            /**
526:             * Closes this iterator.
527:             * This method does not exist in the standard {@link Iterator} or {@link
528:             * ListIterator} interfaces.
529:             *
530:             * <p>After being closed, only the {@link #hasNext} and {@link
531:             * #hasPrevious} methods may be called and these will return false.  {@link
532:             * #close()} may also be called again and will do nothing.  If other
533:             * methods are called a <code>NullPointerException</code> will generally be
534:             * thrown.</p>
535:             *
536:             * @throws RuntimeExceptionWrapper if a {@link DatabaseException} is
537:             * thrown.
538:             */
539:            public void close() {
540:
541:                if (cursor != null) {
542:                    coll.closeCursor(cursor);
543:                    cursor = null;
544:                }
545:            }
546:
547:            /**
548:             * Returns the collection associated with this iterator.
549:             * This method does not exist in the standard {@link Iterator} or {@link
550:             * ListIterator} interfaces.
551:             *
552:             * @return the collection associated with this iterator.
553:             */
554:            public final StoredCollection getCollection() {
555:
556:                return coll;
557:            }
558:
559:            // --- begin BaseIterator methods ---
560:
561:            public final ListIterator dup() {
562:
563:                try {
564:                    StoredIterator o = (StoredIterator) super .clone();
565:                    o.cursor = cursor.cloneCursor();
566:                    return o;
567:                } catch (Exception e) {
568:                    throw StoredContainer.convertException(e);
569:                }
570:            }
571:
572:            public final boolean isCurrentData(Object currentData) {
573:
574:                return (this .currentData == currentData);
575:            }
576:
577:            public final boolean moveToIndex(int index) {
578:
579:                try {
580:                    OperationStatus status = cursor.getSearchKey(new Integer(
581:                            index), null, lockForWrite);
582:                    setAndRemoveAllowed = (status == OperationStatus.SUCCESS);
583:                    return setAndRemoveAllowed;
584:                } catch (Exception e) {
585:                    throw StoredContainer.convertException(e);
586:                }
587:            }
588:
589:            // --- end BaseIterator methods ---
590:
591:            private void moveToCurrent() throws DatabaseException {
592:
593:                if (toCurrent != 0) {
594:                    move(toCurrent);
595:                    toCurrent = 0;
596:                }
597:            }
598:
599:            private OperationStatus move(int direction)
600:                    throws DatabaseException {
601:
602:                switch (direction) {
603:                case MOVE_NEXT:
604:                    if (coll.iterateDuplicates()) {
605:                        return cursor.getNext(lockForWrite);
606:                    } else {
607:                        return cursor.getNextNoDup(lockForWrite);
608:                    }
609:                case MOVE_PREV:
610:                    if (coll.iterateDuplicates()) {
611:                        return cursor.getPrev(lockForWrite);
612:                    } else {
613:                        return cursor.getPrevNoDup(lockForWrite);
614:                    }
615:                case MOVE_FIRST:
616:                    return cursor.getFirst(lockForWrite);
617:                default:
618:                    throw new IllegalArgumentException(String
619:                            .valueOf(direction));
620:                }
621:            }
622:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.