| /******************************************************************************* |
| * 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); |
| } |
| } |