/***************************************************************************** * 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.AbstractSequentialList; import java.util.Iterator; import java.util.List; import java.util.ListIterator; import java.util.NoSuchElementException; /** * A unmodifiable view on a specified list. The view filters the original list * according to the provided filter. */ public class FilteredListView extends AbstractSequentialList<Object> implements List<Object> { /** * */ private List<Object> list; /** * */ private IFilter filter; /** * The cached size. Copute only once, so change in the underlying collection * is not reflected */ private int size = -1; /** * * * @param filter * @param list */ public FilteredListView(List<Object> 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 setBackupList(List 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; } /** * size. * * @return int */ @Override public int size() { if(size == -1) { // compute the size size = 0; Iterator<Object> i = iterator(); while(i.hasNext()) { size++; i.next(); } } return size; } /** * Returns <tt>true</tt> if this collection contains the specified element. * More formally, returns <tt>true</tt> if and only if this collection * contains at least one element <tt>e</tt> such that <tt>(o==null ? e==null : o.equals(e))</tt>. * <p> * * @param o * object to be checked for containment in this collection. * * @return <tt>true</tt> if this collection contains the specified element. */ @Override public boolean contains(Object o) { return list.contains(o); } /** * Removes a single instance of the specified element from this collection, * if it is present (optional operation). More formally, removes an element <tt>e</tt> such that <tt>(o==null ? e==null : * o.equals(e))</tt>, if the collection contains one or more such elements. * Returns <tt>true</tt> if the collection contained the specified element * (or equivalently, if the collection changed as a result of the call). * <p> * * This implementation call the remove method on the underlying collection. * <p> * * @param o * element to be removed from this collection, if present. * * @return <tt>true</tt> if the collection contained the specified element. * * @throws UnsupportedOperationException * if the <tt>remove</tt> method is not supported by this * collection. */ @Override public boolean remove(Object o) { // return list.remove(o); throw new UnsupportedOperationException(); } /** * listIterator. * * @param index * int * * @return ListIterator */ @Override public ListIterator<Object> listIterator(int index) { return new FilteredListIterator(index); } /** * */ private class FilteredListIterator implements ListIterator<Object> { /** * */ Object current; /** * */ Object next; /** * */ Object previous; /** * Index of the current element (last returned) in the backup list. */ int currentIndex; /** * */ int previousIndex; /** * */ int nextIndex; /** * Index of the last returned element. */ int eleIndex = -1; /** * Index of the boundary. */ int index = 0; /** * */ ListIterator<Object> listIterator; /** * * * @param index */ FilteredListIterator(int index) { listIterator = list.listIterator(0); nextIndex = -1; next = nextFilteredObject(); previous = null; previousIndex = -1; current = next; currentIndex = 0; // Go to the specified index while(hasNext() && (nextIndex() < index)) { next(); } } /** * * * @return */ protected Object nextFilteredObject() { while(listIterator.hasNext()) { int curIndex = listIterator.nextIndex(); // This is the current // index in the list Object ele = listIterator.next(); if(filter.isAllowed(ele) && (curIndex > nextIndex)) { nextIndex = curIndex; return ele; } } // end loop return null; } /** * * * @return */ protected Object previousFilteredObject() { while(listIterator.hasPrevious()) { int curIndex = listIterator.previousIndex(); // This is the // current index // in the list Object ele = listIterator.previous(); if(filter.isAllowed(ele) && (curIndex < previousIndex)) { previousIndex = curIndex; return ele; } } // end loop return null; } /** * /** nextIndex. * * @return int */ public int nextIndex() { return index; } /** * previousIndex. * * @return int */ public int previousIndex() { return index - 1; } /** * remove. */ public void remove() { throw new UnsupportedOperationException(); } /** * hasNext. * * @return boolean */ public boolean hasNext() { return next != null; } /** * hasPrevious. * * @return boolean */ public boolean hasPrevious() { return previous != null; } /** * next. * * @return Object */ public Object next() { if(next == null) { throw new NoSuchElementException(); } if(index > eleIndex) { // previous was up, continue previous = current; previousIndex = currentIndex; current = next; currentIndex = nextIndex; next = nextFilteredObject(); index++; eleIndex++; return current; } else { // previous was down, turn back index++; return current; } } /** * previous. * * @return Object */ public Object previous() { if(previous == null) { throw new NoSuchElementException(); } if(index > eleIndex) { // previous was up, turn back index--; return current; } else { // previuos was done, continue next = current; nextIndex = currentIndex; current = previous; currentIndex = previousIndex; previous = previousFilteredObject(); index--; eleIndex--; return current; } } /** * add. * * @param o * Object */ public void add(Object o) { throw new UnsupportedOperationException(); } /** * set. * * @param o * Object */ public void set(Object o) { throw new UnsupportedOperationException(); } } }