public void set(E value) { if (dataObject == null) { throw new IllegalStateException(); } if (!coll.hasValues()) { throw new UnsupportedOperationException(); } DataCursor cursor = null; boolean doAutoCommit = coll.beginAutoCommit(); try { cursor = new DataCursor(coll.view, writeAllowed); if (moveCursor(dataIndex, cursor)) { cursor.putCurrent(value); setSlot(dataIndex, cursor); coll.closeCursor(cursor); coll.commitAutoCommit(doAutoCommit); } else { throw new IllegalStateException(); } } catch (Exception e) { coll.closeCursor(cursor); throw coll.handleException(e, doAutoCommit); } }
public void add(E value) { /* * The checkIterAddAllowed method ensures that one of the following two * conditions holds and throws UnsupportedOperationException otherwise: * 1- This is a list iterator for a recno-renumber database. * 2- This is a collection iterator for a duplicates database. */ coll.checkIterAddAllowed(); OperationStatus status = OperationStatus.SUCCESS; DataCursor cursor = null; boolean doAutoCommit = coll.beginAutoCommit(); try { if (coll.view.keysRenumbered || !coll.areDuplicatesOrdered()) { /* * This is a recno-renumber database or a btree/hash database * with unordered duplicates. */ boolean hasPrev = hasPrevious(); if (!hasPrev && !hasNext()) { /* The collection is empty. */ if (coll.view.keysRenumbered) { /* Append to an empty recno-renumber database. */ status = coll.view.append(value, null, null); } else if (coll.view.dupsAllowed && coll.view.range.isSingleKey()) { /* * When inserting a duplicate into a single-key range, * the main key is fixed, so we can always insert into * an empty collection. */ cursor = new DataCursor(coll.view, writeAllowed); cursor.useRangeKey(); status = cursor.putNoDupData(null, value, null, true); coll.closeCursor(cursor); cursor = null; } else { throw new IllegalStateException("Collection is empty, cannot add() duplicate"); } /* * Move past the record just inserted (the cursor should be * closed above to prevent multiple open cursors in certain * DB core modes). */ if (status == OperationStatus.SUCCESS) { next(); dataIndex = nextIndex - 1; } } else { /* * The collection is non-empty. If hasPrev is true then * the element at (nextIndex - 1) is available; otherwise * the element at nextIndex is available. */ cursor = new DataCursor(coll.view, writeAllowed); int insertIndex = hasPrev ? (nextIndex - 1) : nextIndex; if (!moveCursor(insertIndex, cursor)) { throw new IllegalStateException(); } /* * For a recno-renumber database or a database with * unsorted duplicates, insert before the iterator 'next' * position, or after the 'prev' position. Then adjust * the slots to account for the inserted record. */ status = hasPrev ? cursor.putAfter(value) : cursor.putBefore(value); if (status == OperationStatus.SUCCESS) { insertSlot(nextIndex, cursor); } } } else { /* This is a btree/hash database with ordered duplicates. */ cursor = new DataCursor(coll.view, writeAllowed); if (coll.view.range.isSingleKey()) { /* * When inserting a duplicate into a single-key range, * the main key is fixed. */ cursor.useRangeKey(); } else { /* * When inserting into a multi-key range, the main key * is the last dataIndex accessed by next(), previous() * or add(). */ if (dataIndex < 0 || !moveCursor(dataIndex, cursor)) { throw new IllegalStateException(); } } /* * For a hash/btree with duplicates, insert the duplicate, * put the new record in slot zero, and set the next index * to slot one (past the new record). */ status = cursor.putNoDupData(null, value, null, true); if (status == OperationStatus.SUCCESS) { clearSlots(); setSlot(0, cursor); dataIndex = 0; nextIndex = 1; } } if (status == OperationStatus.KEYEXIST) { throw new IllegalArgumentException("Duplicate value"); } else if (status != OperationStatus.SUCCESS) { throw new IllegalArgumentException("Could not insert: " + status); } /* Prevent subsequent set() or remove() call. */ dataObject = null; coll.closeCursor(cursor); coll.commitAutoCommit(doAutoCommit); } catch (Exception e) { /* Catch RuntimeExceptions too. */ coll.closeCursor(cursor); throw coll.handleException(e, doAutoCommit); } }
public void remove() { if (dataObject == null) { throw new IllegalStateException(); } DataCursor cursor = null; boolean doAutoCommit = coll.beginAutoCommit(); try { cursor = new DataCursor(coll.view, writeAllowed); if (moveCursor(dataIndex, cursor)) { cursor.delete(); deleteSlot(dataIndex); dataObject = null; /* * Repopulate the block after removing all records, using the * cursor position of the deleted record as a starting point. * First try moving forward, since the user was moving forward. * (It is possible to delete all records in the block only by * moving forward, i.e, when nextIndex is greater than * dataIndex.) */ if (nextIndex == 0 && keys[0] == null) { OperationStatus status; for (int i = 0; i < keys.length; i += 1) { status = coll.iterateDuplicates() ? cursor.getNext(false) : cursor.getNextNoDup(false); if (status == OperationStatus.SUCCESS) { setSlot(i, cursor); } else { break; } } /* * If no records are found past the cursor position, try * moving backward. If no records are found before the * cursor position, leave nextIndex set to keys.length, * which is the same as the initial iterator state and is * appropriate for an empty key range. */ if (keys[0] == null) { nextIndex = keys.length; for (int i = nextIndex - 1; i >= 0; i -= 1) { status = coll.iterateDuplicates() ? cursor.getPrev(false) : cursor.getPrevNoDup(false); if (status == OperationStatus.SUCCESS) { setSlot(i, cursor); } else { break; } } } } coll.closeCursor(cursor); coll.commitAutoCommit(doAutoCommit); } else { throw new IllegalStateException(); } } catch (Exception e) { coll.closeCursor(cursor); throw coll.handleException(e, doAutoCommit); } }