/******************************************************************************* * Copyright (c) 2009 - 2010 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.lang.reflect.Array; import java.util.*; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.equinox.p2.metadata.index.IIndexProvider; import org.eclipse.equinox.p2.query.IQuery; import org.eclipse.equinox.p2.query.IQueryResult; /** * A result optimized for dealing with iterators returned from * expression evaluation. */ public class QueryResult<T> implements IQueryResult<T> { private final IRepeatableIterator<T> iterator; private boolean firstUse = true; /** * Create an QueryResult based on the given iterator. The <code>oneShot</code> parameter * can be set to <code>true</code> if the returned instance is expected to be perused * only once. This will allow some optimizations since the result of the iteration doesn't * need to be copied in preparation for a second iteration. * * @param iterator The iterator to use as the result iterator. */ public QueryResult(Iterator<T> iterator) { this.iterator = (iterator instanceof IRepeatableIterator<?>) ? (IRepeatableIterator<T>) iterator : RepeatableIterator.create(iterator); } public QueryResult(Collection<T> collection) { this.iterator = RepeatableIterator.create(collection); } public boolean isEmpty() { return !iterator.hasNext(); } public Iterator<T> iterator() { if (firstUse) { firstUse = false; return iterator; } return iterator.getCopy(); } @SuppressWarnings("unchecked") public T[] toArray(Class<T> clazz) { Object provider = iterator.getIteratorProvider(); if (provider.getClass().isArray()) return (T[]) provider; Collection<T> c = toUnmodifiableSet(); return c.toArray((T[]) Array.newInstance(clazz, c.size())); } @SuppressWarnings("unchecked") public Set<T> toSet() { Object provider = iterator.getIteratorProvider(); if (provider instanceof Collection<?>) return new HashSet<T>((Collection<T>) provider); if (provider instanceof IIndexProvider<?>) return iteratorToSet(((IIndexProvider<T>) provider).everything()); if (provider.getClass().isArray()) { T[] elems = (T[]) provider; int idx = elems.length; HashSet<T> copy = new HashSet<T>(idx); while (--idx >= 0) copy.add(elems[idx]); return copy; } if (provider instanceof Map<?, ?>) return new HashSet<T>((Set<T>) ((Map<?, ?>) provider).entrySet()); return iteratorToSet(iterator()); } public IQueryResult<T> query(IQuery<T> query, IProgressMonitor monitor) { return query.perform(iterator()); } @SuppressWarnings("unchecked") public Set<T> toUnmodifiableSet() { Object provider = iterator.getIteratorProvider(); if (provider instanceof Set<?>) return Collections.unmodifiableSet((Set<T>) provider); if (provider instanceof Map<?, ?>) return Collections.unmodifiableSet((Set<T>) ((Map<?, ?>) provider).entrySet()); return toSet(); } private Set<T> iteratorToSet(Iterator<T> iter) { HashSet<T> set = new HashSet<T>(); while (iter.hasNext()) set.add(iter.next()); return set; } }