/projects/eclipse_SDK-3.7.1/plugins/org.eclipse.equinox.p2.metadata.source_2.1.0.v20110510/org/eclipse/equinox/internal/p2/metadata/index/Index.java
Java | 149 lines | 109 code | 16 blank | 24 comment | 35 complexity | 1702a551e4e5e9ba83579750c9c9c8cd MD5 | raw file
- /*******************************************************************************
- * Copyright (c) 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.index;
- 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;
- public abstract class Index<T> implements IIndex<T> {
- protected static boolean isIndexedMember(IExpression expr, IExpression variable, String memberName) {
- if (expr instanceof Member) {
- Member member = (Member) expr;
- return member.getOperand() == variable && member.getName().equals(memberName);
- }
- return false;
- }
- protected static Object concatenateUnique(Object previous, Object toAdd) {
- if (previous == null || toAdd == null || toAdd == Boolean.FALSE)
- return toAdd;
- if (previous instanceof ArrayList<?>) {
- @SuppressWarnings("unchecked")
- ArrayList<Object> prevArr = (ArrayList<Object>) previous;
- if (!prevArr.contains(toAdd))
- prevArr.add(toAdd);
- return previous;
- }
- if (previous.equals(toAdd))
- return previous;
- ArrayList<Object> arr = new ArrayList<Object>();
- arr.add(previous);
- arr.add(toAdd);
- return arr;
- }
- protected Object getQueriedIDs(IEvaluationContext ctx, IExpression variable, String memberName, IExpression booleanExpr, Object queriedKeys) {
- IExpression targetExpr = booleanExpr;
- if (booleanExpr instanceof IMatchExpression<?>) {
- targetExpr = ((Unary) targetExpr).operand;
- ctx = ((IMatchExpression<?>) booleanExpr).createContext();
- }
- int type = targetExpr.getExpressionType();
- switch (type) {
- case IExpression.TYPE_EQUALS :
- Binary eqExpr = (Binary) targetExpr;
- IExpression lhs = eqExpr.lhs;
- IExpression rhs = eqExpr.rhs;
- if (isIndexedMember(lhs, variable, memberName)) {
- Object val = safeEvaluate(ctx, rhs);
- if (val == null)
- return null;
- return concatenateUnique(queriedKeys, val);
- }
- if (isIndexedMember(rhs, variable, memberName)) {
- Object val = safeEvaluate(ctx, lhs);
- if (val == null)
- return null;
- return concatenateUnique(queriedKeys, val);
- }
- // Not applicable for indexing
- return null;
- case IExpression.TYPE_AND :
- // AND is OK if at least one of the branches require the queried key
- for (IExpression expr : ExpressionUtil.getOperands(targetExpr)) {
- Object test = getQueriedIDs(ctx, variable, memberName, expr, queriedKeys);
- if (test != null) {
- if (test == Boolean.FALSE)
- // Failing exists so the AND will fail altogether
- return test;
- // It's safe to break here since an and'ing several queries
- // for different keys and the same input will yield false anyway.
- return test;
- }
- }
- return null;
- case IExpression.TYPE_OR :
- // OR is OK if all the branches require the queried key
- for (IExpression expr : ExpressionUtil.getOperands(targetExpr)) {
- Object test = getQueriedIDs(ctx, variable, memberName, expr, queriedKeys);
- if (test == null)
- // This branch did not require the key so index cannot be used
- return null;
- if (test == Boolean.FALSE)
- // Branch will always fail regardless of input, so just ignore
- continue;
- queriedKeys = test;
- }
- return queriedKeys;
- case IExpression.TYPE_EXISTS :
- case IExpression.TYPE_ALL :
- // We must evaluate the lhs to find the referenced keys
- //
- CollectionFilter cf = (CollectionFilter) targetExpr;
- Iterator<?> values;
- try {
- values = cf.getOperand().evaluateAsIterator(ctx);
- } catch (IllegalArgumentException e) {
- return null;
- }
- if (!values.hasNext())
- // No keys are requested but we know that an exists must
- // fail at this point. An all will however succeed regardless
- // of what is used as input.
- return type == IExpression.TYPE_ALL ? null : Boolean.FALSE;
- LambdaExpression lambda = cf.lambda;
- IEvaluationContext lambdaCtx = lambda.prolog(ctx);
- Variable lambdaVar = lambda.getItemVariable();
- IExpression filterExpr = lambda.getOperand();
- do {
- lambdaVar.setValue(lambdaCtx, values.next());
- queriedKeys = getQueriedIDs(lambdaCtx, variable, memberName, filterExpr, queriedKeys);
- if (queriedKeys == null)
- // No use continuing. The expression does not require the key
- return null;
- } while (values.hasNext());
- return queriedKeys;
- }
- return null;
- }
- private static Object safeEvaluate(IEvaluationContext ctx, IExpression expr) {
- try {
- return expr.evaluate(ctx);
- } catch (IllegalArgumentException e) {
- return null;
- }
- }
- }