Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'bundles/org.eclipse.equinox.p2.ql')
-rw-r--r--bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Pipe.java132
-rw-r--r--bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/QLFactory.java10
-rw-r--r--bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/WrappedIQuery.java15
-rw-r--r--bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/p2/ql/IQLExpression.java9
-rw-r--r--bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/p2/ql/IQLFactory.java8
-rw-r--r--bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/p2/ql/QLContextQuery.java7
-rw-r--r--bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/p2/ql/QLMatchQuery.java91
7 files changed, 174 insertions, 98 deletions
diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Pipe.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Pipe.java
new file mode 100644
index 000000000..aa74f32c9
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Pipe.java
@@ -0,0 +1,132 @@
+/*******************************************************************************
+ * 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.ql.expression;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import org.eclipse.equinox.internal.p2.metadata.expression.*;
+import org.eclipse.equinox.p2.metadata.expression.*;
+import org.eclipse.equinox.p2.metadata.index.IIndex;
+import org.eclipse.equinox.p2.metadata.index.IIndexProvider;
+import org.eclipse.equinox.p2.ql.IQLExpression;
+import org.eclipse.equinox.p2.ql.IQLFactory;
+
+public class Pipe extends NAry implements IQLExpression {
+
+ private class NoIndexProvider implements IIndexProvider<Object> {
+ private Iterator<Object> everything;
+
+ NoIndexProvider() { //
+ }
+
+ public IIndex<Object> getIndex(String memberName) {
+ return null;
+ }
+
+ public Iterator<Object> everything() {
+ return everything;
+ }
+
+ @SuppressWarnings("unchecked")
+ void setEverything(Iterator<?> everything) {
+ this.everything = (Iterator<Object>) everything;
+ }
+ }
+
+ private static Expression[] makePipeable(Expression[] operands) {
+ // We expect two types of expressions. The ones that act on THIS
+ // i.e. boolean match expressions or the ones that act EVERYTHING
+ // by iterating a collection.
+ //
+ // Our task here is to convert all booleans into collections so
+ // that:
+ // <boolean expression> becomes select(x | <boolean expression)
+ //
+ // If we find consecutive boolean expressions, we can actually
+ // make one more optimization:
+ // <expr1>, <expr2> becomes select(x | <expr1> && <expr2>)
+
+ ArrayList<Expression> pipeables = new ArrayList<Expression>();
+ ArrayList<Expression> booleans = new ArrayList<Expression>();
+ VariableFinder finder = new VariableFinder(ExpressionFactory.EVERYTHING);
+ for (int idx = 0; idx < operands.length; ++idx) {
+ Expression operand = operands[idx];
+ finder.reset();
+ operand.accept(finder);
+ if (finder.isFound()) {
+ if (!booleans.isEmpty()) {
+ // Concatenate all found booleans.
+ pipeables.add(makePipeableOfBooleans(booleans));
+ booleans.clear();
+ }
+ pipeables.add(operand);
+ } else
+ booleans.add(operand);
+ }
+ if (!booleans.isEmpty())
+ pipeables.add(makePipeableOfBooleans(booleans));
+ return pipeables.toArray(new Expression[pipeables.size()]);
+ }
+
+ private static Expression makePipeableOfBooleans(ArrayList<Expression> booleans) {
+ IQLFactory factory = (IQLFactory) ExpressionUtil.getFactory();
+ Expression boolExpr = booleans.get(0);
+ int top = booleans.size();
+ if (top > 1)
+ boolExpr = (Expression) factory.and(booleans.toArray(new IExpression[top]));
+ return (Expression) factory.select(ExpressionFactory.EVERYTHING, factory.lambda(ExpressionFactory.THIS, boolExpr));
+ }
+
+ protected Pipe(Expression[] operands) {
+ super(makePipeable(assertLength(operands, 2, "pipe"))); //$NON-NLS-1$
+ }
+
+ public int getExpressionType() {
+ return TYPE_PIPE;
+ }
+
+ @Override
+ public String getOperator() {
+ return "pipe"; //$NON-NLS-1$
+ }
+
+ @Override
+ public Object evaluate(IEvaluationContext context) {
+ return evaluateAsIterator(context);
+ }
+
+ @Override
+ public Iterator<?> evaluateAsIterator(IEvaluationContext context) {
+ Iterator<?> iterator = operands[0].evaluateAsIterator(context);
+ if (operands.length == 0 || !iterator.hasNext())
+ return iterator;
+
+ Class<Object> elementClass = Object.class;
+ Variable everything = ExpressionFactory.EVERYTHING;
+ IEvaluationContext nextContext = EvaluationContext.create(context, everything);
+ NoIndexProvider noIndexProvider = new NoIndexProvider();
+ nextContext.setIndexProvider(noIndexProvider);
+ for (int idx = 1; idx < operands.length; ++idx) {
+ Expression expr = operands[idx];
+ noIndexProvider.setEverything(iterator);
+ everything.setValue(nextContext, new Everything<Object>(elementClass, noIndexProvider));
+ iterator = expr.evaluateAsIterator(nextContext);
+ if (!iterator.hasNext())
+ break;
+ }
+ return iterator;
+ }
+
+ @Override
+ public int getPriority() {
+ return PRIORITY_COLLECTION;
+ }
+}
diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/QLFactory.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/QLFactory.java
index 8568e680c..5cb9c5c6b 100644
--- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/QLFactory.java
+++ b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/QLFactory.java
@@ -6,6 +6,7 @@ import java.util.*;
import org.eclipse.equinox.internal.p2.metadata.expression.*;
import org.eclipse.equinox.p2.metadata.expression.IExpression;
import org.eclipse.equinox.p2.ql.IQLFactory;
+import org.eclipse.equinox.p2.query.IQuery;
public class QLFactory extends ExpressionFactory implements IQLFactory, IQLConstants {
@SuppressWarnings("hiding")
@@ -102,6 +103,10 @@ public class QLFactory extends ExpressionFactory implements IQLFactory, IQLConst
return new Latest((Expression) collection);
}
+ public IExpression limit(IExpression collection, int count) {
+ return new Limit((Expression) collection, Literal.create(new Integer(count)));
+ }
+
public IExpression limit(IExpression collection, IExpression limit) {
return new Limit((Expression) collection, (Expression) limit);
}
@@ -151,6 +156,11 @@ public class QLFactory extends ExpressionFactory implements IQLFactory, IQLConst
return super.variable(name);
}
+ public IExpression toExpression(IQuery<?> query) {
+ Literal queryConstant = Literal.create(query);
+ return new WrappedIQuery(new Expression[] {queryConstant});
+ }
+
public IExpression unique(IExpression collection, IExpression cache) {
return new Unique((Expression) collection, (Expression) cache);
}
diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/WrappedIQuery.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/WrappedIQuery.java
index 2436976af..2fdfa03e0 100644
--- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/WrappedIQuery.java
+++ b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/WrappedIQuery.java
@@ -19,6 +19,19 @@ import org.eclipse.equinox.p2.query.IQuery;
public final class WrappedIQuery extends Function implements IQLConstants {
+ /**
+ * <p>The WrappedIQuery constructor takes an array with one or two arguments.
+ * The first argument must evaluate to an instance of {@link IQuery}. The second
+ * argument is optional. The following applies:</p><ul>
+ * <li>If first argument evaluates to an instance of {@link IMatchQuery}, then
+ * a provided second argument assumed to be the candidate to match. The
+ * variable <code>this</code> will be used if no second argument is not provided.</li>
+ * <li>For all other types of queries the second argument must evaluate
+ * to an iterator. If it is not provided, it defaults to the variable
+ * <code>everything</code>.
+ * </ul>
+ * @param operands
+ */
public WrappedIQuery(Expression[] operands) {
super(assertLength(operands, 1, 2, KEYWORD_IQUERY));
}
@@ -43,7 +56,7 @@ public final class WrappedIQuery extends Function implements IQLConstants {
if (operands.length > 1)
iterator = operands[1].evaluateAsIterator(context);
else
- iterator = QLFactory.EVERYTHING.evaluateAsIterator(context);
+ iterator = ExpressionFactory.EVERYTHING.evaluateAsIterator(context);
return ((IQuery<Object>) query).perform((Iterator<Object>) iterator);
}
diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/p2/ql/IQLExpression.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/p2/ql/IQLExpression.java
index 905bb85b5..2e6e50a2f 100644
--- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/p2/ql/IQLExpression.java
+++ b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/p2/ql/IQLExpression.java
@@ -13,8 +13,9 @@ public interface IQLExpression extends IExpression {
int TYPE_INTERSECT = 27;
int TYPE_LATEST = 28;
int TYPE_LIMIT = 29;
- int TYPE_SELECT = 30;
- int TYPE_TRAVERSE = 31;
- int TYPE_UNION = 32;
- int TYPE_UNIQUE = 33;
+ int TYPE_PIPE = 30;
+ int TYPE_SELECT = 31;
+ int TYPE_TRAVERSE = 32;
+ int TYPE_UNION = 33;
+ int TYPE_UNIQUE = 34;
}
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 8afa1822f..74d4ee478 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
@@ -14,6 +14,7 @@ import java.util.Map;
import org.eclipse.equinox.p2.metadata.IVersionedId;
import org.eclipse.equinox.p2.metadata.expression.IExpression;
import org.eclipse.equinox.p2.metadata.expression.IExpressionFactory;
+import org.eclipse.equinox.p2.query.IQuery;
/**
* This inteface provides all the factory methods needed to create the all possible
@@ -175,4 +176,11 @@ public interface IQLFactory extends IExpressionFactory {
* @return A collection expression
*/
IExpression unique(IExpression collection, IExpression cache);
+
+ /**
+ * Wrap an {@link IQuery} as an expression.
+ * @param query
+ * @return An expression that wraps the query
+ */
+ IExpression toExpression(IQuery<?> query);
}
diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/p2/ql/QLContextQuery.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/p2/ql/QLContextQuery.java
index b8733d63c..8022adf2d 100644
--- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/p2/ql/QLContextQuery.java
+++ b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/p2/ql/QLContextQuery.java
@@ -12,8 +12,7 @@ package org.eclipse.equinox.p2.ql;
import java.util.Iterator;
import org.eclipse.equinox.internal.p2.ql.expression.QLUtil;
-import org.eclipse.equinox.p2.metadata.expression.ExpressionUtil;
-import org.eclipse.equinox.p2.metadata.expression.IEvaluationContext;
+import org.eclipse.equinox.p2.metadata.expression.*;
import org.eclipse.equinox.p2.metadata.index.IIndexProvider;
import org.eclipse.equinox.p2.metadata.index.IQueryWithIndex;
import org.eclipse.equinox.p2.query.IQueryResult;
@@ -67,6 +66,10 @@ public class QLContextQuery<T> extends QLQuery<T> implements IQueryWithIndex<T>
return result;
}
+ public IExpression getExpression() {
+ return expression;
+ }
+
/**
* Query without using a collector. Instead, return the result of the query directly.
* @param queryContext The context for the query.
diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/p2/ql/QLMatchQuery.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/p2/ql/QLMatchQuery.java
deleted file mode 100644
index 8cd491ab8..000000000
--- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/p2/ql/QLMatchQuery.java
+++ /dev/null
@@ -1,91 +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.ArrayList;
-import java.util.Iterator;
-import org.eclipse.equinox.internal.p2.metadata.expression.EvaluationContext;
-import org.eclipse.equinox.internal.p2.ql.expression.QLFactory;
-import org.eclipse.equinox.internal.p2.ql.expression.QLUtil;
-import org.eclipse.equinox.p2.metadata.expression.*;
-import org.eclipse.equinox.p2.query.IMatchQuery;
-import org.eclipse.equinox.p2.query.IQueryResult;
-
-/**
- * An IQuery implementation that is based on the p2 query language.
- */
-public class QLMatchQuery<T> extends QLQuery<T> implements IMatchQuery<T> {
- private final IMatchExpression<T> expression;
- private IEvaluationContext context;
-
- /**
- * Creates a new query instance with indexed parameters.
- * @param instanceClass The class used for filtering elements before calling {@link #isMatch(Object)}
- * @param expression The expression that represents the query.
- */
- public QLMatchQuery(Class<T> instanceClass, IMatchExpression<T> expression) {
- super(instanceClass);
- this.expression = expression;
- }
-
- /**
- * Creates a new query instance with indexed parameters.
- * @param instanceClass The class used for filtering elements before calling {@link #isMatch(Object)}
- * @param expression The expression that represents the query.
- * @param parameters Parameters to use for the query.
- */
- public QLMatchQuery(Class<T> instanceClass, String expression, Object... parameters) {
- this(instanceClass, ExpressionUtil.getFactory().<T> matchExpression(ExpressionUtil.getParser().parse(expression), parameters));
- }
-
- /**
- * Checks if the <code>candidate</code> object is an instance of the <code>elementClass</code>
- * used by this query. If it is, the result calling {@link IMatchExpression#isMatch(IEvaluationContext, Object)}
- * on the contained expression is returned.
- * @param candidate The object to test
- * @return <code>true</code> if <code>candidate</code> is an instance of the element class and the
- * expression match test returns true.
- */
- public boolean isMatch(T candidate) {
- return elementClass.isInstance(candidate) && expression.isMatch(context, candidate);
- }
-
- public void postPerform() {
- context = null;
- }
-
- public void prePerform() {
- //
- }
-
- public IQueryResult<T> perform(Iterator<T> iterator) {
- if (QLUtil.needsTranslationSupport(expression)) {
- IQueryContext<T> queryContext = QL.newQueryContext(iterator);
- IExpression translations = QLFactory.TRANSLATIONS;
- context = EvaluationContext.create(expression.createContext(), translations);
- context.setValue(translations, queryContext.getTranslationSupport(getLocale()));
- } else
- context = expression.createContext();
-
- prePerform();
- try {
- ArrayList<T> result = new ArrayList<T>();
- while (iterator.hasNext()) {
- T candidate = iterator.next();
- if (isMatch(candidate))
- result.add(candidate);
- }
- return new QueryResult<T>(result);
- } finally {
- postPerform();
- }
- }
-}

Back to the top