blob: b05d22e69686a0cea5a40658aecdcf95b5d5abbd [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2011, 2016 Willink Transformations and others.
* 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:
* E.D.Willink - initial API and implementation
*******************************************************************************/
package org.eclipse.ocl.pivot.internal.utilities;
import java.util.List;
import java.util.NoSuchElementException;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.ocl.pivot.utilities.ClassUtil;
import com.google.common.collect.Iterators;
import com.google.common.collect.UnmodifiableIterator;
/**
* A CompleteElementIterable supports iteration over the multiple iterable contributions
* to a Complete Element as if all were merged in a composite element.
*
* @param <O> The Outer type of the Complete Element
* @param <I> The Inner type of the iterated Complete Element child
*/
public abstract class CompleteElementIterable<O,I> implements Iterable<I>
{
protected class Iterator implements java.util.Iterator<I>
{
private final java.util.Iterator<? extends O> outerIterator;
private java.util.Iterator<I> innerIterator;
private @Nullable I nextValue;
public Iterator(@NonNull Iterable<? extends O> iterables) {
outerIterator = iterables.iterator();
innerIterator = null;
advance();
}
protected boolean advance() {
while (true) {
if (innerIterator != null) {
while (innerIterator.hasNext()) {
nextValue = getInnerValue(ClassUtil.nonNullState(innerIterator.next()));
if (nextValue != null) {
return true;
}
}
}
if (outerIterator.hasNext()) {
Iterable<I> innerIterable = getInnerIterable(ClassUtil.nonNullState(outerIterator.next()));
if (innerIterable != null) {
innerIterator = innerIterable.iterator();
}
}
else {
break;
}
}
nextValue = null;
return false;
}
@Override
public boolean hasNext() {
return nextValue != null;
// if (innerIterator == null) {
// return false;
// }
// if (innerIterator.hasNext()) {
// return true;
// }
// return advance();
}
@Override
public I next() {
try {
if (nextValue != null) {
return nextValue;
}
else {
throw new NoSuchElementException();
}
}
finally {
advance();
}
// return innerIterator != null ? getInnerValue(innerIterator.next()) : null;
}
@Override
public void remove() {
throw new IllegalStateException();
}
}
protected final @NonNull Iterable<? extends O> iterables;
public CompleteElementIterable(@NonNull Iterable<? extends O> iterables) {
this.iterables = iterables;
}
/**
* Return the iterables for an inner iteration over the iterable. A null
* return may be used to indicate no inner iterations are necessary.
*
* @param iterable
* @return the inner iterable or null for none.
*/
protected abstract Iterable<I> getInnerIterable(@NonNull O iterable);
protected @Nullable I getInnerValue(@NonNull I element) {
return element;
}
@Override
public java.util.@NonNull Iterator<I> iterator() {
if (iterables instanceof List<?>) {
@SuppressWarnings("unchecked")
List<O> list = (List<O>)iterables;
if (list.size() == 0) {
@NonNull UnmodifiableIterator<I> result = Iterators.<I>emptyIterator();
return result;
}
else if (list.size() == 1) {
O listEntry = list.get(0);
if (listEntry != null) {
Iterable<I> innerIterable = getInnerIterable(listEntry);
if (innerIterable != null) {
@SuppressWarnings("null") java.util.@NonNull Iterator<I> result = innerIterable.iterator();
return result;
}
}
@NonNull UnmodifiableIterator<I> result = Iterators.<I>emptyIterator();
return result;
}
}
return new Iterator(iterables);
}
}