alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

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

 

new blog posts

 

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.