1 19 20 package org.netbeans.mdr.storagemodel.transientimpl; 21 22 import java.util.ArrayList ; 23 import java.util.Collection ; 24 import java.util.Iterator ; 25 import java.util.HashMap ; 26 import org.netbeans.mdr.persistence.StorageException; 27 import org.netbeans.mdr.persistence.StorageBadRequestException; 28 import org.netbeans.mdr.persistence.SinglevaluedIndex; 29 import org.netbeans.mdr.persistence.MultivaluedIndex; 30 import org.netbeans.mdr.persistence.Storage; 31 import org.netbeans.mdr.storagemodel.MdrStorage; 32 import org.netbeans.mdr.util.DebugException; 33 import org.netbeans.mdr.util.MapEntryImpl; 34 38 public class TransientMultivaluedIndex extends TransientIndex implements MultivaluedIndex { 39 40 protected boolean unique; 41 42 protected class SlotCollection implements Collection { 43 44 protected Object key; 45 protected Collection st; 46 protected SinglevaluedIndex repos; 47 48 public SlotCollection(Object key, Collection st) { 49 this(key, st, null); 50 } 51 52 public SlotCollection(Object key, Collection st, SinglevaluedIndex repos) { 53 this.key = key; 54 this.st = st; 55 this.repos = repos; 56 } 57 58 public boolean add (Object obj) { 59 if (this.repos != null) 60 throw new UnsupportedOperationException (); 61 try { 62 addToCollection(st, key, obj); 63 handleAdd(key, obj); 64 return true; 65 }catch (StorageException se) { 66 throw new DebugException(se.toString()); 67 } 68 } 69 70 public boolean addAll(java.util.Collection collection) { 71 boolean result = false; 72 for (Iterator it = collection.iterator(); it.hasNext();) { 73 result |= this.add(it.next()); 74 } 75 return result; 76 } 77 78 public void clear() { 79 for (Iterator it = this.st.iterator(); it.hasNext();) { 80 Entry e = (Entry) it.next(); 81 it.remove(); 82 e.dispose(); 83 txlog.push( new CompensatingTransaction.RemoveCTx(e.getKey(),e.getValue())); 84 } 85 } 86 87 public boolean contains(Object obj) { 88 if (this.repos != null) 89 throw new UnsupportedOperationException (); 90 expungeStaleEntries(); 91 for (Iterator it = this.st.iterator(); it.hasNext();) { 92 Entry e = (Entry) it.next(); 93 if (obj.equals(e.getValue())) 94 return true; 95 } 96 return false; 97 } 98 99 public boolean containsAll(java.util.Collection collection) { 100 boolean result = true; 101 for (Iterator it = collection.iterator(); it.hasNext();) { 102 result &= contains(it.next()); 103 } 104 return result; 105 } 106 107 public boolean isEmpty() { 108 expungeStaleEntries(); 109 return this.st.size() == 0; 110 } 111 112 public java.util.Iterator iterator() { 113 return new SlotIterator(this.key, this.st, this.repos); 114 } 115 116 public boolean remove(Object obj) { 117 if (this.repos != null) 118 throw new UnsupportedOperationException (); 119 expungeStaleEntries(); 120 for (Iterator it = this.st.iterator(); it.hasNext();) { 121 Entry entry = (Entry) it.next(); 122 if (obj.equals(entry.getValue())) { 123 it.remove(); 124 txlog.push( new CompensatingTransaction.RemoveCTx(entry.getKey(),entry.getValue())); 125 entry.dispose(); 126 return true; 127 } 128 } 129 return false; 130 } 131 132 public boolean removeAll(java.util.Collection collection) { 133 boolean result = false; 134 for (Iterator it = collection.iterator(); it.hasNext(); ) { 135 result |= remove(it.next()); 136 } 137 return result; 138 } 139 140 public boolean retainAll(java.util.Collection collection) { 141 if (this.repos != null) 142 throw new UnsupportedOperationException (); 143 boolean result = false; 144 for (Iterator it = this.st.iterator(); it.hasNext();) { 145 Entry entry = (Entry) it.next(); 146 if (!entry.isValid()) { 147 it.remove(); 148 entry.dispose(); 149 } 150 else if (!collection.contains( entry.getValue())) { 151 it.remove(); 152 entry.dispose(); 153 txlog.push( new CompensatingTransaction.RemoveCTx(entry.getKey(),entry.getValue())); 154 result = true; 155 } 156 } 157 return result; 158 } 159 160 public int size() { 161 expungeStaleEntries(); 162 return this.st.size(); 163 } 164 165 public Object [] toArray() { 166 ArrayList result = this.collectValues(); 167 return result.toArray(); 168 } 169 170 public Object [] toArray(Object [] obj) { 171 ArrayList result = this.collectValues(); 172 return result.toArray(obj); 173 } 174 175 private ArrayList collectValues() { 176 ArrayList result = new ArrayList (); 177 for (Iterator it = this.st.iterator(); it.hasNext();) { 178 Entry entry = (Entry) it.next(); 179 if (!entry.isValid()) { 180 it.remove(); 181 entry.dispose(); 182 } 183 else { 184 try { 185 result.add(map(this.key, entry.getValue(), this.repos)); 186 }catch (StorageException se) { 187 throw new DebugException(se.toString()); 188 } 189 } 190 } 191 return result; 192 } 193 194 } 195 196 protected class MultivaluedEntryKeySet extends EntryKeySet { 197 198 protected ArrayList collectKeys() { 199 ArrayList result = new ArrayList (); 200 for (Iterator it = map.values().iterator(); it.hasNext(); ) { 201 Collection c = (Collection ) it.next(); 202 if (isValidCollection(c)) { 203 result.add(((Entry)c.iterator().next()).getKey()); 204 } 205 } 206 return result; 207 } 208 209 public java.util.Iterator iterator() { 210 return new MultivaluedEntryKeyIterator(); 211 } 212 213 } 214 215 protected class SlotIterator implements Iterator { 216 217 protected Object key; 218 protected SinglevaluedIndex repos; 219 protected Collection collection; 220 protected Iterator innerIt; 221 protected Entry top; 222 protected Entry last; 223 224 public SlotIterator(Collection c) { 225 this(c, null, null); 226 } 227 228 public SlotIterator(Object key, Collection c, SinglevaluedIndex repos) { 229 this(key, c, repos, c.iterator()); 230 } 231 232 protected SlotIterator(Object key, Collection c, SinglevaluedIndex repos, Iterator it) { 233 this.key = key; 234 this.collection = c; 235 this.repos = repos; 236 this.innerIt = it; 237 } 238 239 public boolean hasNext() { 240 while (this.top == null) { 241 if (!this.innerIt.hasNext()) 242 return false; 243 this.top = (Entry) this.innerIt.next(); 244 if (! this.top.isValid()) { 245 this.innerIt.remove(); 246 this.top.dispose(); 247 this.top = null; 248 } 249 } 250 return true; 251 } 252 253 public Object next() { 254 while (this.top == null) { 255 this.top = (Entry) this.innerIt.next(); 256 if (! this.top.isValid()) { 257 this.innerIt.remove(); 258 this.top.dispose(); 259 this.top = null; 260 } 261 } 262 this.last = this.top; 263 this.top = null; 264 try { 265 return map(this.key, this.last.getValue(), this.repos); 266 }catch (StorageException se) { 267 throw new DebugException(se.toString()); 268 } 269 } 270 271 public void remove() { 272 if (this.last == null) 273 throw new IllegalStateException (); 274 this.innerIt.remove(); 275 this.last.dispose(); 276 txlog.push( new CompensatingTransaction.RemoveCTx(this.key, last.getValue())); 277 this.last = null; 278 } 279 } 280 281 282 protected class MultivaluedEntryKeyIterator implements Iterator { 283 284 private Iterator innerIt; 285 private Collection top; 286 private Collection last; 287 288 public MultivaluedEntryKeyIterator() { 289 this.innerIt = map.values().iterator(); 290 } 291 292 public boolean hasNext() { 293 while (top == null) { 294 if (!this.innerIt.hasNext()) 295 return false; 296 top = (Collection ) this.innerIt.next(); 297 if (! isValidCollection(top)) 298 top = null; 299 } 300 return true; 301 } 302 303 public Object next() { 304 while (top == null) { 305 top = (Collection ) this.innerIt.next(); 306 if (! isValidCollection(top)) 307 top = null; 308 } 309 last = top; 310 top = null; 311 return ((Entry)last.iterator(). next()).getKey(); 312 } 313 314 public void remove() { 315 if (last == null) 316 throw new IllegalStateException (); 317 innerIt.remove(); 318 try { 319 handleRemove(((Entry)last.iterator().next()).getKey(), last); 320 }catch (StorageException se) { 321 throw new DebugException(se.toString()); 322 } 323 } 324 } 325 326 327 public TransientMultivaluedIndex(MdrStorage storage, String name, Storage.EntryType keyType, Storage.EntryType valueType, boolean unique) { 328 super(storage, name, keyType, valueType); 329 this.unique = unique; 330 } 331 332 340 public void add(Object key, Object value) throws StorageException { 341 this.addNoTx(key, value); 342 this.handleAdd(key, value); 343 } 344 345 346 347 protected void expungeStaleEntries() { 348 KeyedReference ref = null; 349 while ((ref = (KeyedReference) refQueue.poll()) != null) { 350 ArrayList clearedSlots = new ArrayList (); 351 org.netbeans.mdr.persistence.MOFID key = ref.getLookupKey(); 352 if (!clearedSlots.contains(key)) { 353 Collection c = (Collection ) this.map.get(key); 355 this.expungeCollection(c); 356 clearedSlots.add(key); 357 } 358 } 359 } 360 361 protected SlotCollection createSlotCollection (Object key, Collection c) { 362 return new SlotCollection (key, c); 363 } 364 365 protected SlotCollection createSlotCollection (Object key, Collection c, SinglevaluedIndex repos) { 366 return new SlotCollection (key, c, repos); 367 } 368 369 376 public java.util.Collection getItems(Object key) throws StorageException { 377 if (this.map == null) 378 this.map = new HashMap (); 379 else 380 expungeStaleEntries(); 381 Collection c = (Collection ) this.map.get(key); 382 if (c == null) { 383 c = new ArrayList (); 384 this.map.put(key,c); 385 } 386 return createSlotCollection(key, c); 387 } 388 389 395 public java.util.Collection getObjects(Object key, SinglevaluedIndex repos) throws StorageException { 396 if (this.map == null) 397 this.map = new HashMap (); 398 else 399 expungeStaleEntries(); 400 Collection c = (Collection ) this.map.get(key); 401 if (c == null) { 402 c = new ArrayList (); 403 this.map.put(key, c); 404 } 405 return createSlotCollection(key, c, repos); 406 } 407 408 protected void handleRemove(Object key, Object value) throws StorageException { 409 Collection c = (Collection ) value; 410 for (Iterator it = c.iterator(); it.hasNext();) { 411 Entry e = (Entry) it.next(); 412 it.remove(); 413 e.dispose(); 414 this.txlog.push( new CompensatingTransaction.RemoveCTx(key, e.getValue())); 415 } 416 } 417 418 425 public boolean isUnique() throws StorageException { 426 return this.unique; 427 } 428 429 435 public boolean remove(Object key, Object value) throws StorageException { 436 Object result = this.removeNoTx (key, value); 437 this.txlog.push( new CompensatingTransaction.RemoveCTx(key, result)); 438 return result != null; 439 } 440 441 public java.util.Set keySet() throws StorageException { 442 if (this.map == null) 443 this.map = new HashMap (); 444 return new MultivaluedEntryKeySet(); 445 } 446 447 448 451 public Collection queryByKeyPrefix (Object prefix, SinglevaluedIndex primaryIndex) throws StorageException { 452 if (getKeyType () != Storage.EntryType.STRING) { 453 throw new UnsupportedOperationException ("Key type must be EntryType.STRING"); 454 } 455 if (!(prefix instanceof String )) { 456 throw new StorageBadRequestException ("String object parameter expected."); 457 } 458 459 java.util.List result = new java.util.LinkedList (); 460 Iterator iter = keySet().iterator (); 461 while (iter.hasNext ()) { 462 String key = (String ) iter.next (); 463 if (key.startsWith ((String ) prefix)) { 464 result.add (new MapEntryImpl (key, getObjects (key, primaryIndex))); 465 } 466 } 467 return result; 468 } 469 470 protected Object map(Object key, Object value, SinglevaluedIndex index) throws StorageException { 471 if (index == null) 472 return value; 473 String thisStorage = MdrStorage.getStorageIdFromMofId((org.netbeans.mdr.persistence.MOFID)key); 474 String otherStorage = MdrStorage.getStorageIdFromMofId((org.netbeans.mdr.persistence.MOFID)value); 475 if (thisStorage.equals(otherStorage)) 476 return index.get(value); 477 else 478 return this.storage.resolve(otherStorage, value); 479 } 480 481 protected final void addNoTx(Object key, Object value) throws StorageException { 482 if (this.map == null) { 483 this.map = new HashMap (); 484 } 485 486 ArrayList list = (ArrayList ) this.map.get(key); 487 if (list == null) { 488 list = new ArrayList (); 489 this.map.put(key, list); 490 } 491 this.addToCollection(list, key, value); 492 } 493 494 protected final Object removeNoTx(Object key, Object value) throws StorageException { 495 if (this.map == null) 496 return null; 497 else 498 expungeStaleEntries(); 499 Collection c = (Collection ) this.map.get(key); 500 if (c == null) 501 return null; 502 for (Iterator it = c.iterator(); it.hasNext();) { 503 Entry e = (Entry) it.next(); 504 Object evalue = e.getValue(); 505 if (value.equals(evalue)) { 506 it.remove(); 507 e.dispose(); 508 return evalue; 509 } 510 } 511 return null; 512 } 513 514 private void addToCollection(Collection c, Object key, Object value) throws StorageException { 515 if (this.unique) { 516 for (Iterator it = c.iterator(); it.hasNext();) { 517 Entry e = (Entry) it.next(); 518 if (value.equals(e.getValue())) 519 throw new StorageBadRequestException("Value: "+value+" is already contained."); 520 } 521 } 522 Entry e = new Entry(key, value); 523 c.add(e); 524 } 525 526 private static void expungeCollection(Collection c) { 527 if (c == null) 528 return; 529 for (Iterator it = c.iterator(); it.hasNext();) { 530 Entry e = (Entry) it.next(); 531 if (!e.isValid()) { 532 e.dispose(); 533 it.remove(); 534 } 535 } 536 } 537 538 539 private static boolean isValidCollection(Object obj) { 540 Collection c = (Collection ) obj; 541 if (c.size() == 0) 542 return false; 543 for (Iterator it = c.iterator(); it.hasNext();) { 544 Entry e = (Entry) it.next(); 545 if (!e.isValid()) { 546 it.remove(); 547 e.dispose(); 548 } 549 else 550 return true; 551 } 552 return false; 553 } 554 555 } 556 | Popular Tags |