/*
* Created on Oct 13, 2006 Copyright (C) 2001-6, Anthony Harrison anh23@pitt.edu
* (jactr.org) This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the License,
* or (at your option) any later version. This library is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
* the GNU Lesser General Public License for more details. You should have
* received a copy of the GNU Lesser General Public License along with this
* library; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.jactr.core.utils.collections;
import java.lang.ref.Reference;
import java.lang.ref.SoftReference;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import javolution.util.FastList;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* a collection that permits asynchronous changes to its contents without
* affecting calls to getCachedCopy() Even though it is synchronized, care must
* be taken to synchronize the collection while iterating over it
*
* @author developer
* @param <I>
*/
public class CachedCollection<I> implements Collection<I>
{
/**
* logger definition
*/
static private final Log LOGGER = LogFactory
.getLog(CachedCollection.class);
private Collection<I> _backingCollection;
private Reference<Collection<I>> _cachedCollectionReference;
public CachedCollection(Collection<I> backing)
{
_backingCollection = backing;
_cachedCollectionReference = null;
}
synchronized public boolean add(I arg0)
{
boolean rtn = _backingCollection.add(arg0);
if (rtn) clearCachedValues();
return rtn;
}
synchronized public boolean addAll(Collection< ? extends I> arg0)
{
boolean rtn = _backingCollection.addAll(arg0);
if (rtn) clearCachedValues();
return rtn;
}
synchronized public void clear()
{
_backingCollection.clear();
clearCachedValues();
}
synchronized public boolean contains(Object arg0)
{
return _backingCollection.contains(arg0);
}
synchronized public boolean containsAll(Collection< ? > arg0)
{
return _backingCollection.containsAll(arg0);
}
synchronized public boolean isEmpty()
{
return _backingCollection.isEmpty();
}
synchronized public Iterator<I> iterator()
{
return getCachedValues().iterator();
}
synchronized public boolean remove(Object arg0)
{
boolean rtn = _backingCollection.remove(arg0);
if (rtn) clearCachedValues();
return rtn;
}
synchronized public boolean removeAll(Collection< ? > arg0)
{
boolean rtn = _backingCollection.removeAll(arg0);
if (rtn) clearCachedValues();
return rtn;
}
synchronized public boolean retainAll(Collection< ? > arg0)
{
boolean rtn = _backingCollection.retainAll(arg0);
if (rtn) clearCachedValues();
return rtn;
}
synchronized public int size()
{
return _backingCollection.size();
}
synchronized public Object[] toArray()
{
return _backingCollection.toArray();
}
synchronized public <T> T[] toArray(T[] arg0)
{
return _backingCollection.toArray(arg0);
}
public Collection<I> getBackingValues()
{
return _backingCollection;
}
synchronized public Collection<I> getCachedValues()
{
Collection<I> rtn = null;
if (_cachedCollectionReference == null ||
(rtn = _cachedCollectionReference.get()) == null)
{
rtn = Collections.unmodifiableCollection(new FastList<I>(
_backingCollection));
_cachedCollectionReference = new SoftReference<Collection<I>>(rtn);
}
return rtn;
}
synchronized protected void clearCachedValues()
{
if (_cachedCollectionReference != null) _cachedCollectionReference.clear();
_cachedCollectionReference = null;
}
@Override
synchronized public String toString()
{
return getCachedValues().toString();
}
}