Skip to content

Commit

Permalink
Clean-up IQueryResult and its implementations
Browse files Browse the repository at this point in the history
  • Loading branch information
HannesWell committed Sep 11, 2023
1 parent fb0c40c commit 5058924
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 67 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,31 +14,40 @@
package org.eclipse.equinox.internal.p2.metadata.expression;

import java.lang.reflect.Array;
import java.util.*;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
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.
* 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.
* 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);
this.iterator = (iterator instanceof IRepeatableIterator<T> repeatable) //
? repeatable
: RepeatableIterator.create(iterator);
}

public QueryResult(Collection<T> collection) {
Expand All @@ -63,31 +72,26 @@ public Iterator<T> iterator() {
@SuppressWarnings("unchecked")
public T[] toArray(Class<T> clazz) {
Object provider = iterator.getIteratorProvider();
if (provider.getClass().isArray())
if (provider.getClass().isArray()) {
return (T[]) provider;

Collection<T> c = toUnmodifiableSet();
return c.toArray((T[]) Array.newInstance(clazz, c.size()));
}
return toArray(toUnmodifiableSet(), clazz);
}

@Override
@SuppressWarnings("unchecked")
public Set<T> toSet() {
Object provider = iterator.getIteratorProvider();
if (provider instanceof Collection<?>)
return new HashSet<>((Collection<T>) provider);
if (provider instanceof IIndexProvider<?>)
return iteratorToSet(((IIndexProvider<T>) provider).everything());
if (provider.getClass().isArray()) {
if (provider instanceof Collection collection) {
return new HashSet<>(collection);
} else if (provider instanceof IIndexProvider indexProvider) {
return iteratorToSet(indexProvider.everything());
} else if (provider.getClass().isArray()) {
T[] elems = (T[]) provider;
int idx = elems.length;
HashSet<T> copy = new HashSet<>(idx);
while (--idx >= 0)
copy.add(elems[idx]);
return copy;
return new HashSet<>(Arrays.asList(elems));
} else if (provider instanceof Map<?, ?> map) {
return new HashSet<>((Set<T>) map.entrySet());
}
if (provider instanceof Map<?, ?>)
return new HashSet<>((Set<T>) ((Map<?, ?>) provider).entrySet());
return iteratorToSet(iterator());
}

Expand All @@ -100,17 +104,25 @@ public IQueryResult<T> query(IQuery<T> query, IProgressMonitor monitor) {
@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());
if (provider instanceof Set set) {
return Collections.unmodifiableSet(set);
} else if (provider instanceof Map map) {
return Collections.unmodifiableSet((Set<T>) map.entrySet());
}
return toSet();
}

private Set<T> iteratorToSet(Iterator<T> iter) {
HashSet<T> set = new HashSet<>();
while (iter.hasNext())
Set<T> set = new HashSet<>();
while (iter.hasNext()) {
set.add(iter.next());
}
return set;
}

public static <T> T[] toArray(Collection<T> collection, Class<T> clazz) {
@SuppressWarnings("unchecked")
T[] arr = (T[]) Array.newInstance(clazz, collection == null ? 0 : collection.size());
return collection != null ? collection.toArray(arr) : arr;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,18 @@
*******************************************************************************/
package org.eclipse.equinox.p2.query;

import java.lang.reflect.Array;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.equinox.internal.p2.metadata.expression.QueryResult;

/**
* This class allows to adapt java collections to a p2 a query result and as such something queryable
* This class allows to adapt java collections to a p2 a query result and as
* such something queryable
*
* @since 2.0
*/
public class CollectionResult<T> implements IQueryResult<T> {
Expand All @@ -49,12 +51,7 @@ public Iterator<T> iterator() {

@Override
public T[] toArray(Class<T> clazz) {
int size = collection.size();
@SuppressWarnings("unchecked")
T[] result = (T[]) Array.newInstance(clazz, size);
if (size != 0)
collection.toArray(result);
return result;
return QueryResult.toArray(collection, clazz);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
*******************************************************************************/
package org.eclipse.equinox.p2.query;

import java.lang.reflect.Array;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
Expand All @@ -23,6 +22,7 @@
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.equinox.internal.p2.metadata.Messages;
import org.eclipse.equinox.internal.p2.metadata.expression.QueryResult;

/**
* A collector is a generic visitor that collects objects passed to it, and can
Expand Down Expand Up @@ -51,13 +51,6 @@ public static final <T> Collector<T> emptyCollector() {
return (Collector<T>) EMPTY_COLLECTOR;
}

/**
* Creates a new collector.
*/
public Collector() {
super();
}

/**
* Accepts an object.
* <p>
Expand Down Expand Up @@ -96,8 +89,9 @@ public void addAll(IQueryResult<T> queryResult) {
* @return the collection being used to collect results.
*/
protected Collection<T> getCollection() {
if (collected == null)
if (collected == null) {
collected = new HashSet<>();
}
return collected;
}

Expand All @@ -119,7 +113,7 @@ public boolean isEmpty() {
*/
@Override
public Iterator<T> iterator() {
return collected == null ? Collections.<T>emptyList().iterator() : collected.iterator();
return collected == null ? Collections.emptyIterator() : collected.iterator();
}

/**
Expand All @@ -140,18 +134,13 @@ public int size() {
*/
@Override
public T[] toArray(Class<T> clazz) {
int size = collected == null ? 0 : collected.size();
@SuppressWarnings("unchecked")
T[] result = (T[]) Array.newInstance(clazz, size);
if (size != 0)
collected.toArray(result);
return result;
return QueryResult.toArray(collected, clazz);
}

/**
* Returns a copy of the collected objects.
*
* @return An unmodifiable collection of the collected objects
* @return An modifiable collection of the collected objects
*/
@Override
public Set<T> toSet() {
Expand All @@ -164,8 +153,9 @@ public Set<T> toSet() {
@Override
public IQueryResult<T> query(IQuery<T> query, IProgressMonitor monitor) {
IQueryResult<T> result;
if (monitor == null)
if (monitor == null) {
monitor = new NullProgressMonitor();
}
try {
monitor.beginTask(Messages.performing_subquery, 1);
result = query.perform(iterator());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,25 +18,26 @@
import java.util.Set;

/**
* An IQueryResult represents the results of a query.
* An IQueryResult represents the results of a query.
*
* @since 2.0
*/
public interface IQueryResult<T> extends IQueryable<T>, Iterable<T> {
/**
* Returns whether this QueryResult is empty.
* @return <code>true</code> if this QueryResult has accepted any results,
* and <code>false</code> otherwise.
* Returns whether this QueryResult is empty.
*
* @return <code>true</code> if this QueryResult has accepted any results, and
* <code>false</code> otherwise.
*/
public boolean isEmpty();
boolean isEmpty();

/**
* Returns an iterator on the collected objects.
*
* @return an iterator of the collected objects.
*/
@Override
public Iterator<T> iterator();
Iterator<T> iterator();

/**
* Returns the collected objects as an array
Expand All @@ -46,18 +47,20 @@ public interface IQueryResult<T> extends IQueryable<T>, Iterable<T> {
* @throws ArrayStoreException the runtime type of the specified array is
* not a super-type of the runtime type of every collected object
*/
public T[] toArray(Class<T> clazz);
T[] toArray(Class<T> clazz);

/**
* Creates a new Set copy with the contents of this query result. The
* copy can be altered without any side effects on its origin.
* Creates a new Set copy with the contents of this query result. The copy can
* be altered without any side effects on its origin.
*
* @return A detached copy of the result.
*/
public Set<T> toSet();
Set<T> toSet();

/**
* Returns a Set backed by this query result. The set is immutable.
*
* @return A Set backed by this query result.
*/
public Set<T> toUnmodifiableSet();
Set<T> toUnmodifiableSet();
}

0 comments on commit 5058924

Please sign in to comment.