Skip to main content
summaryrefslogblamecommitdiffstats
blob: e44a4e507727140d66786b6f7197cbdd616e595f (plain) (tree)












































































































































































































































                                                                                                                                                              
/*******************************************************************************
 * Copyright (c) 2009 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.*;
import org.eclipse.equinox.p2.query.IQueryResult;

public class RepeatableIterator<T> implements IRepeatableIterator<T> {
	private final List<T> values;
	private int position = -1;

	@SuppressWarnings("unchecked")
	public static <T> IRepeatableIterator<T> create(Object unknown) {
		if (unknown.getClass().isArray())
			return create((T[]) unknown);
		if (unknown instanceof Iterator<?>)
			return create((Iterator<T>) unknown);
		if (unknown instanceof List<?>)
			return create((List<T>) unknown);
		if (unknown instanceof Collection<?>)
			return create((Collection<T>) unknown);
		if (unknown instanceof Map<?, ?>)
			return create((Set<T>) ((Map<?, ?>) unknown).entrySet());
		if (unknown instanceof IQueryResult<?>)
			return create((IQueryResult<T>) unknown);
		throw new IllegalArgumentException("Cannot convert a " + unknown.getClass().getName() + " into an iterator"); //$NON-NLS-1$ //$NON-NLS-2$
	}

	public static <T> IRepeatableIterator<T> create(Iterator<T> iterator) {
		return iterator instanceof IRepeatableIterator<?> ? ((IRepeatableIterator<T>) iterator).getCopy() : new ElementRetainingIterator<T>(iterator);
	}

	public static <T> IRepeatableIterator<T> create(List<T> values) {
		return new RepeatableIterator<T>(values);
	}

	public static <T> IRepeatableIterator<T> create(Collection<T> values) {
		return new CollectionIterator<T>(values);
	}

	public static <T> IRepeatableIterator<T> create(IQueryResult<T> values) {
		return new QueryResultIterator<T>(values);
	}

	public static <T> IRepeatableIterator<T> create(T[] values) {
		return new ArrayIterator<T>(values);
	}

	RepeatableIterator(List<T> values) {
		this.values = values;
	}

	public IRepeatableIterator<T> getCopy() {
		return new RepeatableIterator<T>(values);
	}

	public boolean hasNext() {
		return position + 1 < values.size();
	}

	public T next() {
		if (++position == values.size()) {
			--position;
			throw new NoSuchElementException();
		}
		return values.get(position);
	}

	public void remove() {
		throw new UnsupportedOperationException();
	}

	public Object getIteratorProvider() {
		return values;
	}

	void setPosition(int position) {
		this.position = position;
	}

	List<T> getValues() {
		return values;
	}

	static class ArrayIterator<T> implements IRepeatableIterator<T> {
		private final T[] array;
		private int position = -1;

		public ArrayIterator(T[] array) {
			this.array = array;
		}

		public Object getIteratorProvider() {
			return array;
		}

		public boolean hasNext() {
			return position + 1 < array.length;
		}

		public T next() {
			if (++position >= array.length)
				throw new NoSuchElementException();
			return array[position];
		}

		public void remove() {
			throw new UnsupportedOperationException();
		}

		public IRepeatableIterator<T> getCopy() {
			return new ArrayIterator<T>(array);
		}
	}

	static class CollectionIterator<T> implements IRepeatableIterator<T> {
		private final Collection<T> collection;

		private final Iterator<T> iterator;

		CollectionIterator(Collection<T> collection) {
			this.collection = collection;
			this.iterator = collection.iterator();
		}

		public IRepeatableIterator<T> getCopy() {
			return new CollectionIterator<T>(collection);
		}

		public Object getIteratorProvider() {
			return collection;
		}

		public boolean hasNext() {
			return iterator.hasNext();
		}

		public T next() {
			return iterator.next();
		}

		public void remove() {
			throw new UnsupportedOperationException();
		}
	}

	static class QueryResultIterator<T> implements IRepeatableIterator<T> {
		private final IQueryResult<T> queryResult;

		private final Iterator<T> iterator;

		QueryResultIterator(IQueryResult<T> queryResult) {
			this.queryResult = queryResult;
			this.iterator = queryResult.iterator();
		}

		public IRepeatableIterator<T> getCopy() {
			return new QueryResultIterator<T>(queryResult);
		}

		public Object getIteratorProvider() {
			return queryResult;
		}

		public boolean hasNext() {
			return iterator.hasNext();
		}

		public T next() {
			return iterator.next();
		}

		public void remove() {
			throw new UnsupportedOperationException();
		}
	}

	static class ElementRetainingIterator<T> extends RepeatableIterator<T> {

		private Iterator<T> innerIterator;

		ElementRetainingIterator(Iterator<T> iterator) {
			super(new ArrayList<T>());
			innerIterator = iterator;
		}

		public synchronized boolean hasNext() {
			if (innerIterator != null) {
				if (innerIterator.hasNext())
					return true;
				innerIterator = null;
				setPosition(getValues().size());
			}
			return super.hasNext();
		}

		public synchronized T next() {
			if (innerIterator != null) {
				T val = innerIterator.next();
				getValues().add(val);
				return val;
			}
			return super.next();
		}

		public synchronized IRepeatableIterator<T> getCopy() {
			// If the current iterator still exists, we must exhaust it first
			//
			exhaustInnerIterator();
			return super.getCopy();
		}

		public synchronized Object getIteratorProvider() {
			exhaustInnerIterator();
			return super.getIteratorProvider();
		}

		private void exhaustInnerIterator() {
			if (innerIterator != null) {
				List<T> values = getValues();
				int savePos = values.size() - 1;
				while (innerIterator.hasNext())
					values.add(innerIterator.next());
				innerIterator = null;
				setPosition(savePos);
			}
		}
	}
}

Back to the top