|
What this is
Other links
The source code/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is NetBeans. The Initial Developer of the Original * Code is Sun Microsystems, Inc. Portions Copyright 1997-2001 Sun * Microsystems, Inc. All Rights Reserved. */ package org.netbeans.mdr.storagemodel.transientimpl; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.HashMap; import org.netbeans.mdr.persistence.StorageException; import org.netbeans.mdr.persistence.StorageBadRequestException; import org.netbeans.mdr.persistence.SinglevaluedIndex; import org.netbeans.mdr.persistence.MultivaluedIndex; import org.netbeans.mdr.persistence.Storage; import org.netbeans.mdr.storagemodel.MdrStorage; import org.netbeans.mdr.util.DebugException; import org.netbeans.mdr.util.MapEntryImpl; /** * * @author Tomas Zezula */ public class TransientMultivaluedIndex extends TransientIndex implements MultivaluedIndex { protected boolean unique; protected class SlotCollection implements Collection { protected Object key; protected Collection st; protected SinglevaluedIndex repos; public SlotCollection(Object key, Collection st) { this(key, st, null); } public SlotCollection(Object key, Collection st, SinglevaluedIndex repos) { this.key = key; this.st = st; this.repos = repos; } public boolean add (Object obj) { if (this.repos != null) throw new UnsupportedOperationException(); try { addToCollection(st, key, obj); handleAdd(key, obj); return true; }catch (StorageException se) { throw new DebugException(se.toString()); } } public boolean addAll(java.util.Collection collection) { boolean result = false; for (Iterator it = collection.iterator(); it.hasNext();) { result |= this.add(it.next()); } return result; } public void clear() { for (Iterator it = this.st.iterator(); it.hasNext();) { Entry e = (Entry) it.next(); it.remove(); e.dispose(); txlog.push( new CompensatingTransaction.RemoveCTx(e.getKey(),e.getValue())); } } public boolean contains(Object obj) { if (this.repos != null) throw new UnsupportedOperationException(); expungeStaleEntries(); for (Iterator it = this.st.iterator(); it.hasNext();) { Entry e = (Entry) it.next(); if (obj.equals(e.getValue())) return true; } return false; } public boolean containsAll(java.util.Collection collection) { boolean result = true; for (Iterator it = collection.iterator(); it.hasNext();) { result &= contains(it.next()); } return result; } public boolean isEmpty() { expungeStaleEntries(); return this.st.size() == 0; } public java.util.Iterator iterator() { return new SlotIterator(this.key, this.st, this.repos); } public boolean remove(Object obj) { if (this.repos != null) throw new UnsupportedOperationException(); expungeStaleEntries(); for (Iterator it = this.st.iterator(); it.hasNext();) { Entry entry = (Entry) it.next(); if (obj.equals(entry.getValue())) { it.remove(); txlog.push( new CompensatingTransaction.RemoveCTx(entry.getKey(),entry.getValue())); entry.dispose(); return true; } } return false; } public boolean removeAll(java.util.Collection collection) { boolean result = false; for (Iterator it = collection.iterator(); it.hasNext(); ) { result |= remove(it.next()); } return result; } public boolean retainAll(java.util.Collection collection) { if (this.repos != null) throw new UnsupportedOperationException(); boolean result = false; for (Iterator it = this.st.iterator(); it.hasNext();) { Entry entry = (Entry) it.next(); if (!entry.isValid()) { it.remove(); entry.dispose(); } else if (!collection.contains( entry.getValue())) { it.remove(); entry.dispose(); txlog.push( new CompensatingTransaction.RemoveCTx(entry.getKey(),entry.getValue())); result = true; } } return result; } public int size() { expungeStaleEntries(); return this.st.size(); } public Object[] toArray() { ArrayList result = this.collectValues(); return result.toArray(); } public Object[] toArray(Object[] obj) { ArrayList result = this.collectValues(); return result.toArray(obj); } private ArrayList collectValues() { ArrayList result = new ArrayList(); for (Iterator it = this.st.iterator(); it.hasNext();) { Entry entry = (Entry) it.next(); if (!entry.isValid()) { it.remove(); entry.dispose(); } else { try { result.add(map(this.key, entry.getValue(), this.repos)); }catch (StorageException se) { throw new DebugException(se.toString()); } } } return result; } } protected class MultivaluedEntryKeySet extends EntryKeySet { protected ArrayList collectKeys() { ArrayList result = new ArrayList(); for (Iterator it = map.values().iterator(); it.hasNext(); ) { Collection c = (Collection) it.next(); if (isValidCollection(c)) { result.add(((Entry)c.iterator().next()).getKey()); } } return result; } public java.util.Iterator iterator() { return new MultivaluedEntryKeyIterator(); } } protected class SlotIterator implements Iterator { protected Object key; protected SinglevaluedIndex repos; protected Collection collection; protected Iterator innerIt; protected Entry top; protected Entry last; public SlotIterator(Collection c) { this(c, null, null); } public SlotIterator(Object key, Collection c, SinglevaluedIndex repos) { this(key, c, repos, c.iterator()); } protected SlotIterator(Object key, Collection c, SinglevaluedIndex repos, Iterator it) { this.key = key; this.collection = c; this.repos = repos; this.innerIt = it; } public boolean hasNext() { while (this.top == null) { if (!this.innerIt.hasNext()) return false; this.top = (Entry) this.innerIt.next(); if (! this.top.isValid()) { this.innerIt.remove(); this.top.dispose(); this.top = null; } } return true; } public Object next() { while (this.top == null) { this.top = (Entry) this.innerIt.next(); if (! this.top.isValid()) { this.innerIt.remove(); this.top.dispose(); this.top = null; } } this.last = this.top; this.top = null; try { return map(this.key, this.last.getValue(), this.repos); }catch (StorageException se) { throw new DebugException(se.toString()); } } public void remove() { if (this.last == null) throw new IllegalStateException(); this.innerIt.remove(); this.last.dispose(); txlog.push( new CompensatingTransaction.RemoveCTx(this.key, last.getValue())); this.last = null; } } protected class MultivaluedEntryKeyIterator implements Iterator { private Iterator innerIt; private Collection top; private Collection last; public MultivaluedEntryKeyIterator() { this.innerIt = map.values().iterator(); } public boolean hasNext() { while (top == null) { if (!this.innerIt.hasNext()) return false; top = (Collection) this.innerIt.next(); if (! isValidCollection(top)) top = null; } return true; } public Object next() { while (top == null) { top = (Collection) this.innerIt.next(); if (! isValidCollection(top)) top = null; } last = top; top = null; return ((Entry)last.iterator(). next()).getKey(); } public void remove() { if (last == null) throw new IllegalStateException(); innerIt.remove(); try { handleRemove(((Entry)last.iterator().next()).getKey(), last); }catch (StorageException se) { throw new DebugException(se.toString()); } } } /** Creates a new instance of TransientMultivaluedIndex */ public TransientMultivaluedIndex(MdrStorage storage, String name, Storage.EntryType keyType, Storage.EntryType valueType, boolean unique) { super(storage, name, keyType, valueType); this.unique = unique; } /** Adds the specified value to values associated in this index with the * specified key. If the index puts limit on number of values associated * with one key and adding value would break this limit, it throws * StorageBadRequestException. * @param key * @param value * @throws StorageException */ public void add(Object key, Object value) throws StorageException { this.addNoTx(key, value); this.handleAdd(key, value); } protected void expungeStaleEntries() { KeyedReference ref = null; while ((ref = (KeyedReference) refQueue.poll()) != null) { ArrayList clearedSlots = new ArrayList(); org.netbeans.mdr.persistence.MOFID key = ref.getLookupKey(); if (!clearedSlots.contains(key)) { // Slot was not cleared but is dirty Collection c = (Collection) this.map.get(key); this.expungeCollection(c); clearedSlots.add(key); } } } protected SlotCollection createSlotCollection (Object key, Collection c) { return new SlotCollection (key, c); } protected SlotCollection createSlotCollection (Object key, Collection c, SinglevaluedIndex repos) { return new SlotCollection (key, c, repos); } /** Returns a collection view of the values associated in the index with specified key. * Returned collection is read only and may not be modified. * If there are no values associated with the key empty collection is returned. * @return * @param key * @throws StorageException */ public java.util.Collection getItems(Object key) throws StorageException { if (this.map == null) this.map = new HashMap(); else expungeStaleEntries(); Collection c = (Collection) this.map.get(key); if (c == null) { c = new ArrayList(); this.map.put(key,c); } return createSlotCollection(key, c); } /** Like getItems, but if the index contains keys, this returns the objects * corresponding to the key * @return * @param key * @throws StorageException */ public java.util.Collection getObjects(Object key, SinglevaluedIndex repos) throws StorageException { if (this.map == null) this.map = new HashMap(); else expungeStaleEntries(); Collection c = (Collection) this.map.get(key); if (c == null) { c = new ArrayList(); this.map.put(key, c); } return createSlotCollection(key, c, repos); } protected void handleRemove(Object key, Object value) throws StorageException { Collection c = (Collection) value; for (Iterator it = c.iterator(); it.hasNext();) { Entry e = (Entry) it.next(); it.remove(); e.dispose(); this.txlog.push( new CompensatingTransaction.RemoveCTx(key, e.getValue())); } } /** If true, the collection of values is contrained to hold * no more than one of any value. * @throws StorageException * @param key * @param repos where to fetch objects from * @return */ public boolean isUnique() throws StorageException { return this.unique; } /** Removes the first occurrence of the specified element in the list * of values associated with the specified key. * @return true if this index changed as a result of this call * @param key * @param value */ public boolean remove(Object key, Object value) throws StorageException { Object result = this.removeNoTx (key, value); this.txlog.push( new CompensatingTransaction.RemoveCTx(key, result)); return result != null; } public java.util.Set keySet() throws StorageException { if (this.map == null) this.map = new HashMap(); return new MultivaluedEntryKeySet(); } /** * Returns key-value pairs, where the key contains the queried prefix. */ public Collection queryByKeyPrefix (Object prefix, SinglevaluedIndex primaryIndex) throws StorageException { if (getKeyType () != Storage.EntryType.STRING) { throw new UnsupportedOperationException ("Key type must be EntryType.STRING"); } if (!(prefix instanceof String)) { throw new StorageBadRequestException ("String object parameter expected."); } java.util.List result = new java.util.LinkedList (); Iterator iter = keySet().iterator (); while (iter.hasNext ()) { String key = (String) iter.next (); if (key.startsWith ((String) prefix)) { result.add (new MapEntryImpl (key, getObjects (key, primaryIndex))); } } return result; } protected Object map(Object key, Object value, SinglevaluedIndex index) throws StorageException { if (index == null) return value; String thisStorage = MdrStorage.getStorageIdFromMofId((org.netbeans.mdr.persistence.MOFID)key); String otherStorage = MdrStorage.getStorageIdFromMofId((org.netbeans.mdr.persistence.MOFID)value); if (thisStorage.equals(otherStorage)) return index.get(value); else return this.storage.resolve(otherStorage, value); } protected final void addNoTx(Object key, Object value) throws StorageException { if (this.map == null) { this.map = new HashMap(); } ArrayList list = (ArrayList) this.map.get(key); if (list == null) { list = new ArrayList(); this.map.put(key, list); } this.addToCollection(list, key, value); } protected final Object removeNoTx(Object key, Object value) throws StorageException { if (this.map == null) return null; else expungeStaleEntries(); Collection c = (Collection) this.map.get(key); if (c == null) return null; for (Iterator it = c.iterator(); it.hasNext();) { Entry e = (Entry) it.next(); Object evalue = e.getValue(); if (value.equals(evalue)) { it.remove(); e.dispose(); return evalue; } } return null; } private void addToCollection(Collection c, Object key, Object value) throws StorageException { if (this.unique) { for (Iterator it = c.iterator(); it.hasNext();) { Entry e = (Entry) it.next(); if (value.equals(e.getValue())) throw new StorageBadRequestException("Value: "+value+" is already contained."); } } Entry e = new Entry(key, value); c.add(e); } private static void expungeCollection(Collection c) { if (c == null) return; for (Iterator it = c.iterator(); it.hasNext();) { Entry e = (Entry) it.next(); if (!e.isValid()) { e.dispose(); it.remove(); } } } private static boolean isValidCollection(Object obj) { Collection c = (Collection) obj; if (c.size() == 0) return false; for (Iterator it = c.iterator(); it.hasNext();) { Entry e = (Entry) it.next(); if (!e.isValid()) { it.remove(); e.dispose(); } else return true; } return false; } } |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.