Skip to main content
summaryrefslogtreecommitdiffstats
blob: bf3ab6ebe2cbc9aadaaffc4020696b6a995c12b8 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
/*******************************************************************************
 * Copyright (c) 2009, 2017 Cloudsmith Inc. 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:
 *     Cloudsmith Inc. - initial API and implementation
 *******************************************************************************/
package org.eclipse.equinox.internal.p2.metadata.expression;

import java.util.Iterator;
import java.util.NoSuchElementException;

/**
 * A CompoundIterator will assume that its contained iterator that will produce
 * elements that in turn can be represented as iterators. The elements of those
 * iterators will be returned in sequence, thus removing one iterator dimension.
 * Elements of the contained iterator that are not iterators will be coerced
 * into iterators using {@link RepeatableIterator#create(Object)}.
 */
public class CompoundIterator<T> implements Iterator<T> {
	private static final Object NO_ELEMENT = new Object();
	private final Iterator<? extends Object> iteratorIterator;
	private Iterator<T> currentIterator;

	private T nextObject = noElement();

	/**
	 * Creates a compound iterator that will iterated over the elements
	 * of the provided <code>iterator</code>. Each element will be coerced
	 * into an iterator and its elements in turn are returned
	 * in succession by the compound iterator.
	 *
	 * @param iterator
	 */
	public CompoundIterator(Iterator<? extends Object> iterator) {
		this.iteratorIterator = iterator;
	}

	@Override
	public boolean hasNext() {
		return positionNext();
	}

	@Override
	public T next() {
		if (!positionNext())
			throw new NoSuchElementException();

		T nxt = nextObject;
		nextObject = noElement();
		return nxt;
	}

	/**
	 * Remove is not supported by this iterator so calling this method
	 * will always yield an exception.
	 * @throws UnsupportedOperationException
	 */
	@Override
	public void remove() {
		throw new UnsupportedOperationException();
	}

	@SuppressWarnings("unchecked")
	private boolean positionNext() {
		if (nextObject != NO_ELEMENT)
			return true;

		while (currentIterator == null || !currentIterator.hasNext()) {
			if (!iteratorIterator.hasNext())
				return false;

			Object nextItor = iteratorIterator.next();
			currentIterator = (nextItor instanceof Iterator<?>) ? (Iterator<T>) nextItor : RepeatableIterator.<T> create(nextItor);
		}
		nextObject = currentIterator.next();
		return true;
	}

	@SuppressWarnings("unchecked")
	private static <T> T noElement() {
		return (T) NO_ELEMENT;
	}
}

Back to the top