Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Hallgren2010-02-22 08:37:08 -0500
committerThomas Hallgren2010-02-22 08:37:08 -0500
commitaa84d673b8dc77ac4c018cc5b09c33020befdeb9 (patch)
treea550076f6d93c2a253d2fac79ff9471c55bd0f36
parentfe5098e97528432f807151c743c89d4b1a1dd20d (diff)
downloadrt.equinox.p2-aa84d673b8dc77ac4c018cc5b09c33020befdeb9.tar.gz
rt.equinox.p2-aa84d673b8dc77ac4c018cc5b09c33020befdeb9.tar.xz
rt.equinox.p2-aa84d673b8dc77ac4c018cc5b09c33020befdeb9.zip
302201 : Unify the two query approaches used in p2, step 5.
-rw-r--r--bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/expression/ExpressionFactory.java8
-rw-r--r--bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/p2/metadata/expression/IExpressionFactory.java16
-rw-r--r--bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/p2/metadata/query/ExpressionContextQuery.java4
-rw-r--r--bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/p2/query/CompoundQuery.java236
-rw-r--r--bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/p2/query/ICompositeQuery.java27
-rw-r--r--bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/p2/ql/IContextExpression.java46
-rw-r--r--bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/p2/ql/IQLFactory.java16
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/core/ContextQuery.java (renamed from bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/p2/query/ContextQuery.java)4
8 files changed, 94 insertions, 263 deletions
diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/expression/ExpressionFactory.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/expression/ExpressionFactory.java
index 46bc7f55d..01bee7640 100644
--- a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/expression/ExpressionFactory.java
+++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/expression/ExpressionFactory.java
@@ -80,6 +80,10 @@ public class ExpressionFactory implements IExpressionFactory, IExpressionConstan
return new LambdaExpression((Variable) variable, (Expression) body);
}
+ public IExpression intersect(IExpression c1, IExpression c2) {
+ throw failNoQL();
+ }
+
public IExpression latest(IExpression collection) {
throw failNoQL();
}
@@ -155,6 +159,10 @@ public class ExpressionFactory implements IExpressionFactory, IExpressionConstan
throw failNoQL();
}
+ public IExpression union(IExpression c1, IExpression c2) {
+ throw failNoQL();
+ }
+
public IExpression variable(String name) {
if (VARIABLE_EVERYTHING.equals(name))
return EVERYTHING;
diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/p2/metadata/expression/IExpressionFactory.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/p2/metadata/expression/IExpressionFactory.java
index a86891b94..62a787c37 100644
--- a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/p2/metadata/expression/IExpressionFactory.java
+++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/p2/metadata/expression/IExpressionFactory.java
@@ -131,6 +131,14 @@ public interface IExpressionFactory {
IExpression indexedParameter(int index);
/**
+ * Create an <i>intersection</i> of <code>c1</code> and <code>c2</code>
+ * @param c1 first collection
+ * @param c2 second collection
+ * @return An intersect expression
+ */
+ IExpression intersect(IExpression c1, IExpression c2);
+
+ /**
* Creates a lambda expression that takes exactly one variable. Suitable for use
* in most collection expressions.
* @param variable The element variable that the lambda uses
@@ -259,6 +267,14 @@ public interface IExpressionFactory {
IExpression toExpression(IQuery<?> query);
/**
+ * Create a <i>union</i> of <code>c1</code> and <code>c2</code>
+ * @param c1 first collection
+ * @param c2 second collection
+ * @return A union expression
+ */
+ IExpression union(IExpression c1, IExpression c2);
+
+ /**
* Creates an expression that represents a variable
* @param name The name of the variable
* @return A variable expression
diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/p2/metadata/query/ExpressionContextQuery.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/p2/metadata/query/ExpressionContextQuery.java
index 9862a83fb..186500089 100644
--- a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/p2/metadata/query/ExpressionContextQuery.java
+++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/p2/metadata/query/ExpressionContextQuery.java
@@ -21,7 +21,7 @@ import org.eclipse.equinox.p2.query.*;
* A query that evaluates using an iterator as input and produces a new iterator.
* @since 2.0
*/
-public class ExpressionContextQuery<T> extends ContextQuery<T> implements IQueryWithIndex<T> {
+public class ExpressionContextQuery<T> implements IQueryWithIndex<T> {
private final IContextExpression<T> expression;
private final Class<? extends T> elementClass;
@@ -54,7 +54,7 @@ public class ExpressionContextQuery<T> extends ContextQuery<T> implements IQuery
return expression;
}
- protected static <T> Class<? extends T> getElementClass(IQuery<T> query) {
+ public static <T> Class<? extends T> getElementClass(IQuery<T> query) {
@SuppressWarnings("unchecked")
Class<? extends T> elementClass = (Class<T>) Object.class;
if (query instanceof ExpressionQuery<?>)
diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/p2/query/CompoundQuery.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/p2/query/CompoundQuery.java
index 69e2170ff..0b3e93a86 100644
--- a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/p2/query/CompoundQuery.java
+++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/p2/query/CompoundQuery.java
@@ -12,10 +12,11 @@
*******************************************************************************/
package org.eclipse.equinox.p2.query;
-import java.util.*;
-import org.eclipse.equinox.p2.metadata.expression.IExpression;
-import org.eclipse.equinox.p2.metadata.index.IIndexProvider;
-import org.eclipse.equinox.p2.metadata.index.IQueryWithIndex;
+import org.eclipse.equinox.internal.p2.metadata.expression.ExpressionFactory;
+import org.eclipse.equinox.internal.p2.metadata.expression.Expression.VariableFinder;
+import org.eclipse.equinox.p2.metadata.expression.*;
+import org.eclipse.equinox.p2.metadata.query.ExpressionContextQuery;
+import org.eclipse.equinox.p2.metadata.query.ExpressionQuery;
/**
* A query that combines a group of sub-queries.<P>
@@ -26,15 +27,12 @@ import org.eclipse.equinox.p2.metadata.index.IQueryWithIndex;
* Clients are expected to call {@link CompoundQuery#createCompoundQuery(IQuery[], boolean)}
* to create a concrete instance of a CompoundQuery. If all Queries are instances of
* {@link IMatchQuery} then the resulting compound query will be an {@link IMatchQuery}, otherwise the
- * resulting query will be a {@link ContextQuery}.
+ * resulting query will be a context query}.
*
* @noextend This class is not intended to be subclassed by clients.
* @since 2.0
*/
-public abstract class CompoundQuery<T> implements ICompositeQuery<T>, IQueryWithIndex<T> {
- IQuery<T>[] queries;
- boolean and;
-
+public abstract class CompoundQuery<T> {
/**
* Creates a compound query that combines the given queries. The queries
* will be performed by the compound query in the given order. This method
@@ -49,179 +47,75 @@ public abstract class CompoundQuery<T> implements ICompositeQuery<T>, IQueryWith
* @param and <code>true</code> if this query represents a logical 'and', and
* <code>false</code> if this query represents a logical 'or'.
*/
- public static <T> IQuery<T> createCompoundQuery(IQuery<T>[] queries, boolean and) {
- if (isMatchQueries(queries)) {
- return new CompoundQuery.MatchCompoundQuery<T>(queries, and);
- }
- return new CompoundQuery.ContextCompoundQuery<T>(queries, and);
- }
-
@SuppressWarnings("unchecked")
- public static <T> IQuery<T> createCompoundQuery(IQuery<T> query1, IQuery<T> query2, boolean and) {
- return createCompoundQuery(new IQuery[] {query1, query2}, and);
- }
-
- /**
- * Returns the queries that make up this compound query
- *
- * @return the queries that make up this compound query
- */
- public List<IQuery<T>> getQueries() {
- return Arrays.asList(queries);
- }
-
- /**
- * Returns whether this compound query combines its queries with a logical
- * 'and' or 'or'.
- * @return <code>true</code> if this query represents a logical 'and', and
- * <code>false</code> if this query represents a logical 'or'.
- */
- public boolean isAnd() {
- return and;
- }
-
- protected CompoundQuery(IQuery<T>[] queries, boolean and) {
- this.queries = queries;
- this.and = and;
- }
-
- /**
- * @param queries
- */
- private static boolean isMatchQueries(IQuery<?>[] queries) {
- for (int i = 0; i < queries.length; i++) {
- if (!(queries[i] instanceof IMatchQuery<?>)) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * The compound query instantiated when all queries are Match Queries.
- */
- private static class MatchCompoundQuery<T> extends CompoundQuery<T> implements IMatchQuery<T> {
-
- protected MatchCompoundQuery(IQuery<T>[] queries, boolean and) {
- super(queries, and);
- }
-
- public boolean isMatch(T candidate) {
- for (int i = 0; i < queries.length; i++) {
- boolean valid = ((IMatchQuery<T>) queries[i]).isMatch(candidate);
- // if we are OR'ing then the first time we find a requirement that is met, return success
- if (valid && !and)
- return true;
- // if we are AND'ing then the first time we find a requirement that is NOT met, return failure
- if (!valid && and)
- return false;
- }
- // if we get past the requirements check and we are AND'ing then return true
- // since all requirements must have been met. If we are OR'ing then return false
- // since none of the requirements were met.
- return and;
- }
-
- /**
- * Performs this query on the given iterator, passing all objects in the iterator
- * that match the criteria of this query to the given result.
- */
- public final IQueryResult<T> perform(Iterator<T> iterator) {
- Collector<T> result = new Collector<T>();
- while (iterator.hasNext()) {
- T candidate = iterator.next();
- if (isMatch(candidate))
- if (!result.accept(candidate))
- break;
+ public static <E> IQuery<E> createCompoundQuery(IQuery<E>[] queries, boolean and) {
+ IExpressionFactory factory = ExpressionUtil.getFactory();
+ int idx = queries.length;
+ if (idx == 1)
+ return queries[0];
+
+ Class<? extends E> elementClass = (Class<E>) Object.class;
+ if (idx == 0)
+ return new ExpressionQuery<E>(elementClass, ExpressionQuery.matchAll());
+
+ IExpression[] expressions = new IExpression[idx];
+ boolean justBooleans = true;
+ boolean justContexts = true;
+ while (--idx >= 0) {
+ IQuery<E> query = queries[idx];
+ if (query instanceof IMatchQuery<?>)
+ justContexts = false;
+ else
+ justBooleans = false;
+
+ IExpression expr = query.getExpression();
+ if (expr == null)
+ expr = factory.toExpression(query);
+
+ Class<? extends E> ec = ExpressionContextQuery.getElementClass(query);
+ if (elementClass == null)
+ elementClass = ec;
+ else if (elementClass != ec) {
+ if (elementClass.isAssignableFrom(ec)) {
+ if (and)
+ // Use most restrictive class
+ elementClass = ec;
+ } else if (ec.isAssignableFrom(elementClass)) {
+ if (!and)
+ // Use least restrictive class
+ elementClass = ec;
+ }
}
- return result;
+ expressions[idx] = expr;
}
- }
-
- /**
- * The compound query instantiated when any of the queries are not
- * match queries.
- */
- private static class ContextCompoundQuery<T> extends CompoundQuery<T> {
- protected ContextCompoundQuery(IQuery<T>[] queries, boolean and) {
- super(queries, and);
+ if (justBooleans) {
+ IExpression compound = and ? factory.and(expressions) : factory.or(expressions);
+ return new ExpressionQuery<E>(elementClass, compound);
}
- public IQueryResult<T> perform(Iterator<T> iterator) {
- if (queries.length < 1)
- return Collector.emptyCollector();
-
- if (queries.length == 1)
- return queries[0].perform(iterator);
-
- Collection<T> data = new ArrayList<T>();
- while (iterator.hasNext())
- data.add(iterator.next());
-
- Set<T> result;
- if (isAnd()) {
- result = queries[0].perform(data.iterator()).unmodifiableSet();
- for (int i = 1; i < queries.length && result.size() > 0; i++) {
- HashSet<T> retained = new HashSet<T>();
- Iterator<T> itor = queries[i].perform(data.iterator()).iterator();
- while (itor.hasNext()) {
- T nxt = itor.next();
- if (result.contains(nxt))
- retained.add(nxt);
- }
- result = retained;
- }
- } else {
- result = queries[0].perform(data.iterator()).toSet();
- for (int i = 1; i < queries.length; i++) {
- Iterator<T> itor = queries[i].perform(data.iterator()).iterator();
- while (itor.hasNext()) {
- result.add(itor.next());
- }
- }
- }
- return new CollectionResult<T>(result);
+ if (!justContexts) {
+ // Mix of boolean queries and context queries. All must be converted into context then.
+ for (idx = 0; idx < expressions.length; ++idx)
+ expressions[idx] = makeContextExpression(factory, expressions[idx]);
}
- }
- public IExpression getExpression() {
- return null;
+ IExpression compound = expressions[0];
+ for (idx = 1; idx < expressions.length; ++idx)
+ compound = and ? factory.intersect(compound, expressions[idx]) : factory.union(compound, expressions[idx]);
+ return new ExpressionContextQuery<E>(elementClass, compound);
}
- public IQueryResult<T> perform(IIndexProvider<T> indexProvider) {
- if (queries.length < 1)
- return Collector.emptyCollector();
-
- if (queries.length == 1)
- return doPerform(queries[0], indexProvider);
-
- Set<T> result;
- if (isAnd()) {
- result = doPerform(queries[0], indexProvider).unmodifiableSet();
- for (int i = 1; i < queries.length && result.size() > 0; i++) {
- HashSet<T> retained = new HashSet<T>();
- Iterator<T> itor = doPerform(queries[i], indexProvider).iterator();
- while (itor.hasNext()) {
- T nxt = itor.next();
- if (result.contains(nxt))
- retained.add(nxt);
- }
- result = retained;
- }
- } else {
- result = doPerform(queries[0], indexProvider).toSet();
- for (int i = 1; i < queries.length; i++) {
- Iterator<T> itor = doPerform(queries[i], indexProvider).iterator();
- while (itor.hasNext()) {
- result.add(itor.next());
- }
- }
- }
- return new CollectionResult<T>(result);
+ @SuppressWarnings("unchecked")
+ public static <T> IQuery<T> createCompoundQuery(IQuery<T> query1, IQuery<T> query2, boolean and) {
+ return createCompoundQuery(new IQuery[] {query1, query2}, and);
}
- private static <Q> IQueryResult<Q> doPerform(IQuery<Q> first, IIndexProvider<Q> indexProvider) {
- return first instanceof IQueryWithIndex<?> ? ((IQueryWithIndex<Q>) first).perform(indexProvider) : first.perform(indexProvider.everything());
+ private static IExpression makeContextExpression(IExpressionFactory factory, IExpression expr) {
+ VariableFinder finder = new VariableFinder(ExpressionFactory.EVERYTHING);
+ expr.accept(finder);
+ if (!finder.isFound())
+ expr = factory.select(ExpressionFactory.EVERYTHING, factory.lambda(ExpressionFactory.THIS, expr));
+ return expr;
}
}
diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/p2/query/ICompositeQuery.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/p2/query/ICompositeQuery.java
deleted file mode 100644
index 1b0baeae5..000000000
--- a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/p2/query/ICompositeQuery.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*******************************************************************************
-* Copyright (c) 2009, 2010 EclipseSource 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:
-* EclipseSource - initial API and implementation
-******************************************************************************/
-package org.eclipse.equinox.p2.query;
-
-import java.util.List;
-
-/**
- * A query that contains a number of sub queries. All queries that support sub-queries
- * should implement this interface so clients can access the sub queries.
- * @since 2.0
- */
-public interface ICompositeQuery<T> extends IQuery<T> {
-
- /**
- * Returns all the child queries of a CompositeQuery.
- * @return All the child queries.
- */
- public List<IQuery<T>> getQueries();
-
-}
diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/p2/ql/IContextExpression.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/p2/ql/IContextExpression.java
deleted file mode 100644
index 31e25c3cb..000000000
--- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/p2/ql/IContextExpression.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*******************************************************************************
- * 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.p2.ql;
-
-import java.util.Iterator;
-import org.eclipse.equinox.p2.metadata.expression.IEvaluationContext;
-import org.eclipse.equinox.p2.metadata.index.IIndexProvider;
-
-/**
- * This is an expression that will need access to the global variable
- * <code>everything</code>.
- */
-public interface IContextExpression<T> extends org.eclipse.equinox.p2.metadata.expression.IContextExpression<T> {
-
- /**
- * <p>Creates a new context to be passed to a subsequent evaluation. The context
- * will have the variable 'everything' set to an expression that represents
- * the <code>everything</code> iterator filtered for instances of <code>elementClass</code>.</p>
- * <p>The values of the iterator will be copied if necessary (when everything is referenced
- * more then once).</p>
- * @param indexProvider The index provider that represents all queried material.
- * @param translations A translation support object to be assigned to the variable 'translations'
- * @return A new evaluation context.
- */
- IEvaluationContext createContext(Class<T> elementClass, IIndexProvider<T> indexProvider, ITranslationSupport translations);
-
- /**
- * <p>Creates a new context to be passed to a subsequent evaluation. The context
- * will have the variable 'everything' set to an expression that represents
- * the <code>everything</code> iterator filtered for instances of <code>elementClass</code>.</p>
- * <p>The values of the iterator will be copied if necessary (when everything is referenced
- * more then once).</p>
- * @param everything The iterator that represents all queried material.
- * @param translations A translation support object to be assigned to the variable 'translations'
- * @return A new evaluation context.
- */
- IEvaluationContext createContext(Class<T> elementClass, Iterator<T> everything, ITranslationSupport translations);
-}
diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/p2/ql/IQLFactory.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/p2/ql/IQLFactory.java
index 8bb69d055..120d6a077 100644
--- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/p2/ql/IQLFactory.java
+++ b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/p2/ql/IQLFactory.java
@@ -88,14 +88,6 @@ public interface IQLFactory extends IExpressionFactory {
Map<String, ? extends Object> getFunctionMap();
/**
- * Create an <i>intersection</i> of <code>c1</code> and <code>c2</code>
- * @param c1 first collection
- * @param c2 second collection
- * @return An intersect expression
- */
- IExpression intersect(IExpression c1, IExpression c2);
-
- /**
* Creates a lambda expression that takes more then one variable (currying). Suitable for use
* in most collection expressions.
* @param variable The element variable that the lambda uses
@@ -132,14 +124,6 @@ public interface IQLFactory extends IExpressionFactory {
IExpression traverse(IExpression collection, IExpression lambda);
/**
- * Create a <i>union</i> of <code>c1</code> and <code>c2</code>
- * @param c1 first collection
- * @param c2 second collection
- * @return A union expression
- */
- IExpression union(IExpression c1, IExpression c2);
-
- /**
* Create an expression that yields a new collection where each element is unique. An
* optional <code>cache</code> can be provided if the uniqueness should span a larger
* scope then just the source collection.
diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/p2/query/ContextQuery.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/core/ContextQuery.java
index 7131ec402..adaebd75d 100644
--- a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/p2/query/ContextQuery.java
+++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/core/ContextQuery.java
@@ -7,7 +7,9 @@
* Contributors:
* EclipseSource - initial API and implementation
******************************************************************************/
-package org.eclipse.equinox.p2.query;
+package org.eclipse.equinox.p2.tests.core;
+
+import org.eclipse.equinox.p2.query.*;
import java.util.Iterator;
import org.eclipse.equinox.p2.metadata.expression.IExpression;

Back to the top