1 8 9 package com.sleepycat.persist; 10 11 import java.util.ArrayList ; 12 import java.util.Iterator ; 13 import java.util.List ; 14 15 import com.sleepycat.bind.EntityBinding; 16 import com.sleepycat.bind.EntryBinding; 17 import com.sleepycat.je.Cursor; 18 import com.sleepycat.je.CursorConfig; 19 import com.sleepycat.je.Database; 20 import com.sleepycat.je.DatabaseEntry; 21 import com.sleepycat.je.DatabaseException; 22 import com.sleepycat.je.JoinCursor; 23 import com.sleepycat.je.LockMode; 24 import com.sleepycat.je.OperationStatus; 25 import com.sleepycat.je.Transaction; 26 27 67 public class EntityJoin<PK,E> { 68 69 private PrimaryIndex<PK,E> primary; 70 private List <Condition> conditions; 71 72 77 public EntityJoin(PrimaryIndex<PK,E> index) { 78 primary = index; 79 conditions = new ArrayList <Condition>(); 80 } 81 82 91 public <SK> void addCondition(SecondaryIndex<SK,PK,E> index, SK key) { 92 93 94 DatabaseEntry keyEntry = new DatabaseEntry(); 95 index.getKeyBinding().objectToEntry(key, keyEntry); 96 97 98 Database db = index.getKeysDatabase(); 99 if (db == null) { 100 db = index.getDatabase(); 101 } 102 103 104 conditions.add(new Condition(db, keyEntry)); 105 } 106 107 118 public ForwardCursor<E> entities() 119 throws DatabaseException { 120 121 return entities(null, null); 122 } 123 124 140 public ForwardCursor<E> entities(Transaction txn, CursorConfig config) 141 throws DatabaseException { 142 143 return new JoinForwardCursor<E>(txn, config, false); 144 } 145 146 158 public ForwardCursor<PK> keys() 159 throws DatabaseException { 160 161 return keys(null, null); 162 } 163 164 181 public ForwardCursor<PK> keys(Transaction txn, CursorConfig config) 182 throws DatabaseException { 183 184 return new JoinForwardCursor<PK>(txn, config, true); 185 } 186 187 private static class Condition { 188 189 private Database db; 190 private DatabaseEntry key; 191 192 Condition(Database db, DatabaseEntry key) { 193 this.db = db; 194 this.key = key; 195 } 196 197 Cursor openCursor(Transaction txn, CursorConfig config) 198 throws DatabaseException { 199 200 OperationStatus status; 201 Cursor cursor = db.openCursor(txn, config); 202 try { 203 DatabaseEntry data = BasicIndex.NO_RETURN_ENTRY; 204 status = cursor.getSearchKey(key, data, null); 205 } catch (DatabaseException e) { 206 try { 207 cursor.close(); 208 } catch (DatabaseException ignored) {} 209 throw e; 210 } 211 if (status == OperationStatus.SUCCESS) { 212 return cursor; 213 } else { 214 cursor.close(); 215 return null; 216 } 217 } 218 } 219 220 private class JoinForwardCursor<V> implements ForwardCursor<V> { 221 222 private Cursor[] cursors; 223 private JoinCursor joinCursor; 224 private boolean doKeys; 225 226 JoinForwardCursor(Transaction txn, CursorConfig config, boolean doKeys) 227 throws DatabaseException { 228 229 this.doKeys = doKeys; 230 try { 231 cursors = new Cursor[conditions.size()]; 232 for (int i = 0; i < cursors.length; i += 1) { 233 Condition cond = conditions.get(i); 234 Cursor cursor = cond.openCursor(txn, config); 235 if (cursor == null) { 236 237 doClose(null); 238 return; 239 } 240 cursors[i] = cursor; 241 } 242 joinCursor = primary.getDatabase().join(cursors, null); 243 } catch (DatabaseException e) { 244 245 doClose(e); 246 } 247 } 248 249 public V next() 250 throws DatabaseException { 251 252 return next(null); 253 } 254 255 public V next(LockMode lockMode) 256 throws DatabaseException { 257 258 if (joinCursor == null) { 259 return null; 260 } 261 if (doKeys) { 262 DatabaseEntry key = new DatabaseEntry(); 263 OperationStatus status = joinCursor.getNext(key, lockMode); 264 if (status == OperationStatus.SUCCESS) { 265 EntryBinding binding = primary.getKeyBinding(); 266 return (V) binding.entryToObject(key); 267 } 268 } else { 269 DatabaseEntry key = new DatabaseEntry(); 270 DatabaseEntry data = new DatabaseEntry(); 271 OperationStatus status = 272 joinCursor.getNext(key, data, lockMode); 273 if (status == OperationStatus.SUCCESS) { 274 EntityBinding binding = primary.getEntityBinding(); 275 return (V) binding.entryToObject(key, data); 276 } 277 } 278 return null; 279 } 280 281 public Iterator <V> iterator() { 282 return iterator(null); 283 } 284 285 public Iterator <V> iterator(LockMode lockMode) { 286 return new BasicIterator<V>(this, lockMode); 287 } 288 289 public void close() 290 throws DatabaseException { 291 292 doClose(null); 293 } 294 295 private void doClose(DatabaseException firstException) 296 throws DatabaseException { 297 298 if (joinCursor != null) { 299 try { 300 joinCursor.close(); 301 joinCursor = null; 302 } catch (DatabaseException e) { 303 if (firstException == null) { 304 firstException = e; 305 } 306 } 307 } 308 for (int i = 0; i < cursors.length; i += 1) { 309 Cursor cursor = cursors[i]; 310 if (cursor != null) { 311 try { 312 cursor.close(); 313 cursors[i] = null; 314 } catch (DatabaseException e) { 315 if (firstException == null) { 316 firstException = e; 317 } 318 } 319 } 320 } 321 if (firstException != null) { 322 throw firstException; 323 } 324 } 325 } 326 } 327 | Popular Tags |