001: /* ***** BEGIN LICENSE BLOCK *****
002: * Version: MPL 1.1
003: * The contents of this file are subject to the Mozilla Public License Version
004: * 1.1 (the "License"); you may not use this file except in compliance with
005: * the License. You may obtain a copy of the License at
006: * http://www.mozilla.org/MPL/
007: *
008: * Software distributed under the License is distributed on an "AS IS" basis,
009: * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
010: * for the specific language governing rights and limitations under the
011: * License.
012: *
013: * The Original Code is Riot.
014: *
015: * The Initial Developer of the Original Code is
016: * Neteye GmbH.
017: * Portions created by the Initial Developer are Copyright (C) 2007
018: * the Initial Developer. All Rights Reserved.
019: *
020: * Contributor(s):
021: * Felix Gnass [fgnass at neteye dot de]
022: *
023: * ***** END LICENSE BLOCK ***** */
024: package org.riotfamily.common.collection;
025:
026: import java.lang.ref.Reference;
027: import java.lang.ref.WeakReference;
028: import java.util.AbstractCollection;
029: import java.util.ArrayList;
030: import java.util.Collection;
031: import java.util.Iterator;
032:
033: import org.apache.commons.logging.Log;
034: import org.apache.commons.logging.LogFactory;
035:
036: /**
037: * Collection whose values are stored as {@link WeakReference weak references}.
038: *
039: * @author Felix Gnass [fgnass at neteye dot de]
040: * @since 6.4
041: */
042: public class WeakReferenceCollection extends AbstractCollection {
043:
044: private static final Log log = LogFactory
045: .getLog(WeakReferenceCollection.class);
046:
047: private Collection references = new ArrayList();
048:
049: /**
050: * Returns an iterator over all non-cleared values.
051: */
052: public Iterator iterator() {
053: return new ReferentIterator();
054: }
055:
056: /**
057: * Returns the number of references. The number may include references that
058: * have already been cleared. To get an exact count call
059: * {@link #purge()} before.
060: */
061: public int size() {
062: return references.size();
063: }
064:
065: /**
066: * Adds a {@link WeakReference} referring to the given value to the internal
067: * collection of references.
068: */
069: public boolean add(Object value) {
070: references.add(new WeakReference(value));
071: return true;
072: }
073:
074: /**
075: * Clears the collection.
076: */
077: public void clear() {
078: references.clear();
079: }
080:
081: /**
082: * Removes all cleared references from the internal collection.
083: */
084: public void purge() {
085: Iterator it = iterator();
086: while (it.hasNext()) {
087: it.next();
088: }
089: }
090:
091: private class ReferentIterator implements Iterator {
092:
093: private Iterator it = references.iterator();
094:
095: private Object nextValue = null;
096:
097: public boolean hasNext() {
098: while (it.hasNext()) {
099: Reference ref = (Reference) it.next();
100: nextValue = ref.get();
101: if (nextValue == null) {
102: log.debug("Item cleared, removing reference.");
103: it.remove();
104: } else {
105: return true;
106: }
107: }
108: return false;
109: }
110:
111: public Object next() {
112: return nextValue;
113: }
114:
115: public void remove() {
116: it.remove();
117: }
118:
119: }
120: }
|