/*****************************************************************************
* Copyright (c) 2008 CEA LIST.
*
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Cedric Dumoulin Cedric.dumoulin@lifl.fr - Initial API and implementation
*
*****************************************************************************/
package org.eclipse.papyrus.infra.core.utils;
import java.util.AbstractCollection;
import java.util.Collection;
import java.util.Iterator;
import java.util.NoSuchElementException;
/**
* A unmodifiable view on a specified list. The view filters the original list
* according to the provided filter.
*/
public class FilteredCollectionView<T> extends AbstractCollection<T> implements Collection<T> {
/** The original collection */
private Collection<T> list;
/** The filter for the view */
private IFilter filter;
/**
* The cached size. Compute only once, so change in the underlying
* collection is not reflected
*/
private int size = -1;
/**
* Creates a new FilteredCollectionView.
*
* @param list
* the list to filter
* @param filter
* the filter for the view
*/
public FilteredCollectionView(Collection<T> list, IFilter filter) {
this.list = list;
this.filter = filter;
}
/**
* Sets the value of the list property.
*
* @param aList
* the new value of the list property
*/
public void setBackupCollection(Collection<T> aList) {
list = aList;
}
/**
* Sets the value of the filter property.
*
* @param aFilter
* the new value of the filter property
*/
public void setFilter(IFilter aFilter) {
filter = aFilter;
}
/**
* Returns the value of the filter property.
*
* @return the new value of the filter property
*/
public IFilter getFilter() {
return filter;
}
/**
* The size of the filtered list.
*
* @return the number of elements in the filtered list
*/
@Override
public int size() {
if(size == -1) { // compute the size
size = 0;
Iterator<T> i = iterator();
while(i.hasNext()) {
size++;
i.next();
}
}
return size;
}
/**
* Return true if the filteredCollection contains the object.
*
* @see java.util.AbstractCollection#contains(java.lang.Object)
* @param o
* @return
*
*/
@Override
public boolean contains(Object o) {
return list.contains(o);
}
/**
* remove the object. Throw an UnsupportedOperationException, as the
* FilteredCollection is ReadOnly.
*
* @see java.util.AbstractCollection#remove(java.lang.Object)
* @param o
* @return
*
*/
@Override
public boolean remove(Object o) {
throw new UnsupportedOperationException();
}
/**
* Return the value to be returned by the iterator.next() method. This
* method can be overloaded by subclasses in order to return another value
* than the objects belonging to the underlying list.
*
* @param ele
* The iterated object. This is the object iterated inside the
* underlying list.
* @return
*/
protected T returnedValue(T ele) {
return ele;
}
/**
* listIterator.
*
* @return ListIterator
*/
@Override
public Iterator<T> iterator() {
return new FilteredIterator();
}
/**
* Iterator other the filtered collection
*/
private class FilteredIterator implements Iterator<T> {
/** the next object */
T next;
/** The original list iterator */
Iterator<T> listIterator;
/**
* Creates a new FilteredIterator
*/
public FilteredIterator() {
listIterator = list.iterator();
next = nextFilteredObject();
}
/**
* Unsupported operation, as this is just a view of a list.
*/
public void remove() {
throw new UnsupportedOperationException();
}
/**
* Returns the next object of the list, when filter is applied
*
* @return
*/
protected T nextFilteredObject() {
while(listIterator.hasNext()) {
T ele = listIterator.next();
if(filter.isAllowed(ele)) {
return returnedValue(ele);
}
} // end loop
return null;
}
/**
* hasNext.
*
* @return boolean
*/
public boolean hasNext() {
return next != null;
}
/**
* Compute the next field (null or next value), and return the previous
* value of the next field.
*
* @return Object
*/
public T next() {
if(next == null) {
throw new NoSuchElementException();
}
T ele = next;
next = nextFilteredObject();
return ele;
}
}
}