blob: 8dcd8c6f7d663b67718b59af0d3132c3661599f9 [file] [log] [blame]
/*******************************************************************************
* 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.InstallableUnit;
import org.eclipse.equinox.internal.p2.metadata.expression.*;
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
import org.eclipse.equinox.p2.metadata.KeyWithLocale;
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 final IIndexProvider<?> indexProvider;
private Iterator<Object> everything;
NoIndexProvider(IIndexProvider<?> indexProvider) { //
this.indexProvider = indexProvider;
}
public IIndex<Object> getIndex(String memberName) {
return null;
}
public Iterator<Object> everything() {
return everything;
}
public Object getManagedProperty(Object client, String memberName, Object key) {
if (indexProvider != null)
return indexProvider.getManagedProperty(client, memberName, key);
if (client instanceof IInstallableUnit && memberName.equals(InstallableUnit.MEMBER_TRANSLATED_PROPERTIES)) {
IInstallableUnit iu = (IInstallableUnit) client;
return key instanceof KeyWithLocale ? iu.getProperty(((KeyWithLocale) key).getKey()) : iu.getProperty(key.toString());
}
return null;
}
@SuppressWarnings("unchecked")
void setEverything(Iterator<?> everything) {
this.everything = (Iterator<Object>) everything;
}
}
public static Expression createPipe(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>)
IQLFactory factory = (IQLFactory) ExpressionUtil.getFactory();
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(factory, booleans));
booleans.clear();
}
pipeables.add(operand);
} else
booleans.add(operand);
}
if (!booleans.isEmpty()) {
if (pipeables.isEmpty())
return normalizeBoolean(factory, booleans);
pipeables.add(makePipeableOfBooleans(factory, booleans));
}
int top = pipeables.size();
if (top > 1)
return new Pipe(pipeables.toArray(new Expression[top]));
return (top == 1) ? pipeables.get(0) : Literal.TRUE_CONSTANT;
}
private static Expression normalizeBoolean(IExpressionFactory factory, ArrayList<Expression> booleans) {
int top = booleans.size();
Expression boolExpr;
if (top > 1)
boolExpr = (Expression) factory.and(booleans.toArray(new IExpression[top]));
else if (top == 1)
boolExpr = booleans.get(0);
else
boolExpr = Literal.TRUE_CONSTANT;
return boolExpr;
}
private static Expression makePipeableOfBooleans(IQLFactory factory, ArrayList<Expression> booleans) {
Expression boolExpr = normalizeBoolean(factory, booleans);
return (Expression) factory.select(ExpressionFactory.EVERYTHING, factory.lambda(ExpressionFactory.THIS, boolExpr));
}
private Pipe(Expression[] operands) {
super(operands);
}
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(context.getIndexProvider());
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;
}
}