1 /*-
2  * See the file LICENSE for redistribution information.
3  *
4  * Copyright (c) 2000, 2010 Oracle and/or its affiliates.  All rights reserved.
5  *
6  */
7 
8 package com.sleepycat.collections;
9 
10 import java.util.Set;
11 
12 import com.sleepycat.bind.EntityBinding;
13 import com.sleepycat.bind.EntryBinding;
14 import com.sleepycat.je.Database;
15 import com.sleepycat.je.DatabaseEntry;
16 /* <!-- begin JE only --> */
17 import com.sleepycat.je.EnvironmentFailureException; // for javadoc
18 import com.sleepycat.je.OperationFailureException; // for javadoc
19 /* <!-- end JE only --> */
20 import com.sleepycat.je.OperationStatus;
21 import com.sleepycat.util.RuntimeExceptionWrapper;
22 
23 /**
24  * The Set returned by Map.values() and Map.duplicates(), and which can also be
25  * constructed directly if a Map is not needed.
26  * Although this collection is a set it may contain duplicate values.  Only if
27  * an entity value binding is used are all elements guaranteed to be unique.
28  *
29  * @author Mark Hayes
30  */
31 public class StoredValueSet<E> extends StoredCollection<E> implements Set<E> {
32 
33     /*
34      * This class is also used internally for the set returned by duplicates().
35      */
36 
37     /**
38      * Creates a value set view of a {@link Database}.
39      *
40      * @param database is the Database underlying the new collection.
41      *
42      * @param valueBinding is the binding used to translate between value
43      * buffers and value objects.
44      *
45      * @param writeAllowed is true to create a read-write collection or false
46      * to create a read-only collection.
47      *
48      * @throws IllegalArgumentException if formats are not consistently
49      * defined or a parameter is invalid.
50      *
51      * @throws RuntimeExceptionWrapper if a checked exception is thrown,
52      * including a {@code DatabaseException} on BDB (C Edition).
53      */
StoredValueSet(Database database, EntryBinding<E> valueBinding, boolean writeAllowed)54     public StoredValueSet(Database database,
55                           EntryBinding<E> valueBinding,
56                           boolean writeAllowed) {
57 
58         super(new DataView(database, null, valueBinding, null,
59                            writeAllowed, null));
60     }
61 
62     /**
63      * Creates a value set entity view of a {@link Database}.
64      *
65      * @param database is the Database underlying the new collection.
66      *
67      * @param valueEntityBinding is the binding used to translate between
68      * key/value buffers and entity value objects.
69      *
70      * @param writeAllowed is true to create a read-write collection or false
71      * to create a read-only collection.
72      *
73      * @throws IllegalArgumentException if formats are not consistently
74      * defined or a parameter is invalid.
75      *
76      * @throws RuntimeExceptionWrapper if a checked exception is thrown,
77      * including a {@code DatabaseException} on BDB (C Edition).
78      */
StoredValueSet(Database database, EntityBinding<E> valueEntityBinding, boolean writeAllowed)79     public StoredValueSet(Database database,
80                           EntityBinding<E> valueEntityBinding,
81                           boolean writeAllowed) {
82 
83         super(new DataView(database, null, null, valueEntityBinding,
84                            writeAllowed, null));
85     }
86 
StoredValueSet(DataView valueSetView)87     StoredValueSet(DataView valueSetView) {
88 
89         super(valueSetView);
90     }
91 
92     /**
93      * Adds the specified entity to this set if it is not already present
94      * (optional operation).
95      * This method conforms to the {@link Set#add} interface.
96      *
97      * @param entity is the entity to be added.
98      *
99      * @return true if the entity was added, that is the key-value pair
100      * represented by the entity was not previously present in the collection.
101      *
102      * <!-- begin JE only -->
103      * @throws OperationFailureException if one of the <a
104      * href="../je/OperationFailureException.html#writeFailures">Write
105      * Operation Failures</a> occurs.
106      *
107      * @throws EnvironmentFailureException if an unexpected, internal or
108      * environment-wide failure occurs.
109      * <!-- end JE only -->
110      *
111      * @throws UnsupportedOperationException if the collection is read-only,
112      * if the collection is indexed, or if an entity binding is not used.
113      *
114      * @throws RuntimeExceptionWrapper if a checked exception is thrown,
115      * including a {@code DatabaseException} on BDB (C Edition).
116      */
add(E entity)117     public boolean add(E entity) {
118 
119         if (view.isSecondary()) {
120             throw new UnsupportedOperationException
121                 ("Add not allowed with index");
122         } else if (view.range.isSingleKey()) {
123             /* entity is actually just a value in this case */
124             if (!view.dupsAllowed) {
125                 throw new UnsupportedOperationException("Duplicates required");
126             }
127             DataCursor cursor = null;
128             boolean doAutoCommit = beginAutoCommit();
129             try {
130                 cursor = new DataCursor(view, true);
131                 cursor.useRangeKey();
132                 OperationStatus status =
133                     cursor.putNoDupData(null, entity, null, true);
134                 closeCursor(cursor);
135                 commitAutoCommit(doAutoCommit);
136                 return (status == OperationStatus.SUCCESS);
137             } catch (Exception e) {
138                 closeCursor(cursor);
139                 throw handleException(e, doAutoCommit);
140             }
141         } else if (view.entityBinding == null) {
142             throw new UnsupportedOperationException
143                 ("Add requires entity binding");
144         } else {
145             return add(null, entity);
146         }
147     }
148 
149     /**
150      * Returns true if this set contains the specified element.
151      * This method conforms to the {@link java.util.Set#contains}
152      * interface.
153      *
154      * @param value the value to check.
155      *
156      * @return whether the set contains the given value.
157      *
158      * <!-- begin JE only -->
159      * @throws OperationFailureException if one of the <a
160      * href="../je/OperationFailureException.html#readFailures">Read Operation
161      * Failures</a> occurs.
162      *
163      * @throws EnvironmentFailureException if an unexpected, internal or
164      * environment-wide failure occurs.
165      * <!-- end JE only -->
166      *
167      * @throws RuntimeExceptionWrapper if a checked exception is thrown,
168      * including a {@code DatabaseException} on BDB (C Edition).
169      */
contains(Object value)170     public boolean contains(Object value) {
171 
172         return containsValue(value);
173     }
174 
175     /**
176      * Removes the specified value from this set if it is present (optional
177      * operation).
178      * If an entity binding is used, the key-value pair represented by the
179      * given entity is removed.  If an entity binding is used, the first
180      * occurrence of a key-value pair with the given value is removed.
181      * This method conforms to the {@link Set#remove} interface.
182      *
183      * <!-- begin JE only -->
184      * @throws OperationFailureException if one of the <a
185      * href="../je/OperationFailureException.html#writeFailures">Write
186      * Operation Failures</a> occurs.
187      *
188      * @throws EnvironmentFailureException if an unexpected, internal or
189      * environment-wide failure occurs.
190      * <!-- end JE only -->
191      *
192      * @throws UnsupportedOperationException if the collection is read-only.
193      *
194      * @throws RuntimeExceptionWrapper if a checked exception is thrown,
195      * including a {@code DatabaseException} on BDB (C Edition).
196      */
remove(Object value)197     public boolean remove(Object value) {
198 
199         return removeValue(value);
200     }
201 
makeIteratorData(BaseIterator iterator, DatabaseEntry keyEntry, DatabaseEntry priKeyEntry, DatabaseEntry valueEntry)202     E makeIteratorData(BaseIterator iterator,
203                        DatabaseEntry keyEntry,
204                        DatabaseEntry priKeyEntry,
205                        DatabaseEntry valueEntry) {
206 
207         return (E) view.makeValue(priKeyEntry, valueEntry);
208     }
209 
hasValues()210     boolean hasValues() {
211 
212         return true;
213     }
214 }
215