/*******************************************************************************
* Copyright (c) 2008, 2014 Stuart McCulloch
* 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:
* Stuart McCulloch - initial API and implementation
*******************************************************************************/
package org.eclipse.sisu.peaberry.cache;
import java.util.Iterator;
import java.util.NoSuchElementException;
import org.eclipse.sisu.peaberry.AttributeFilter;
import org.eclipse.sisu.peaberry.Import;
/**
* Filtered iterable over dynamic collection of {@link AbstractServiceImport}s.
* <p>
* The iterator provided by this view is valid even if the underlying collection
* of services changes - because it keeps track of where it would be in the list
* based on the service id and ranking.
*
* @author mcculls@gmail.com (Stuart McCulloch)
*/
final class FilteredIterableService<T>
implements Iterable<Import<T>> {
final AbstractServiceListener<T> listener;
final AttributeFilter filter;
FilteredIterableService(final AbstractServiceListener<T> listener, final AttributeFilter filter) {
this.listener = listener;
this.filter = filter;
}
public Iterator<Import<T>> iterator() {
return new Iterator<Import<T>>() {
// track where we've been...
private Import<T> prevImport;
private Import<T> nextImport;
public boolean hasNext() {
return null != findNextImport();
}
public Import<T> next() {
if (null == findNextImport()) {
throw new NoSuchElementException();
}
// used cached result
prevImport = nextImport;
nextImport = null;
return prevImport;
}
private Import<T> findNextImport() {
if (null == nextImport) {
// based on our last result and the current list, find next result...
final Import<T> tempImport = listener.findNextImport(prevImport, filter);
// ...and cache it
if (null != tempImport) {
prevImport = null;
nextImport = tempImport;
}
}
return nextImport;
}
public void remove() {
throw new UnsupportedOperationException();
}
};
}
@Override
public boolean equals(final Object rhs) {
if (rhs instanceof FilteredIterableService<?>) {
final FilteredIterableService<?> iterable = (FilteredIterableService<?>) rhs;
return listener.equals(iterable.listener) && equals(filter, iterable.filter);
}
return false;
}
@Override
public int hashCode() {
return listener.hashCode() ^ (null == filter ? 0 : filter.hashCode());
}
private static boolean equals(final Object lhs, final Object rhs) {
return null == lhs ? null == rhs : lhs.equals(rhs);
}
}