diff options
author | Thomas Hallgren | 2010-01-13 12:59:44 +0000 |
---|---|---|
committer | Thomas Hallgren | 2010-01-13 12:59:44 +0000 |
commit | 62eb06de9e9564748a3048f99f307c32a984b214 (patch) | |
tree | 28d62c65462ccffbb66b32f133eba01430d51da4 /bundles/org.eclipse.equinox.p2.ql | |
parent | 81026456fefe243425035fa2f1091d6810eff8e3 (diff) | |
download | rt.equinox.p2-62eb06de9e9564748a3048f99f307c32a984b214.tar.gz rt.equinox.p2-62eb06de9e9564748a3048f99f307c32a984b214.tar.xz rt.equinox.p2-62eb06de9e9564748a3048f99f307c32a984b214.zip |
298604 : Split the p2QL into one core simple Expression part and one Query part
Diffstat (limited to 'bundles/org.eclipse.equinox.p2.ql')
74 files changed, 1205 insertions, 3673 deletions
diff --git a/bundles/org.eclipse.equinox.p2.ql/.settings/.api_filters b/bundles/org.eclipse.equinox.p2.ql/.settings/.api_filters new file mode 100644 index 000000000..dfbf53e91 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.ql/.settings/.api_filters @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<component id="org.eclipse.equinox.p2.ql" version="2"> + <resource path="src/org/eclipse/equinox/internal/p2/ql/expression/WrappedIQuery.java" type="org.eclipse.equinox.internal.p2.ql.expression.WrappedIQuery"> + <filter id="640712815"> + <message_arguments> + <message_argument value="IMatchQuery<T>"/> + <message_argument value="WrappedIQuery"/> + <message_argument value="isMatch(T)"/> + </message_arguments> + </filter> + </resource> + <resource path="src/org/eclipse/equinox/p2/ql/QLMatchQuery.java" type="org.eclipse.equinox.p2.ql.QLMatchQuery"> + <filter id="574619656"> + <message_arguments> + <message_argument value="IMatchQuery<T>"/> + <message_argument value="QLMatchQuery<T>"/> + </message_arguments> + </filter> + </resource> + <resource path="src/org/eclipse/equinox/p2/ql/QLQuery.java" type="org.eclipse.equinox.p2.ql.QLQuery"> + <filter id="574619656"> + <message_arguments> + <message_argument value="IQuery<T>"/> + <message_argument value="QLQuery<T>"/> + </message_arguments> + </filter> + </resource> +</component> diff --git a/bundles/org.eclipse.equinox.p2.ql/META-INF/MANIFEST.MF b/bundles/org.eclipse.equinox.p2.ql/META-INF/MANIFEST.MF index da22b4c74..8eb989b7d 100644 --- a/bundles/org.eclipse.equinox.p2.ql/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.equinox.p2.ql/META-INF/MANIFEST.MF @@ -12,9 +12,12 @@ Bundle-RequiredExecutionEnvironment: J2SE-1.5, Bundle-ActivationPolicy: lazy Import-Package: org.eclipse.equinox.internal.p2.core.helpers, org.eclipse.equinox.internal.p2.metadata, + org.eclipse.equinox.internal.p2.metadata.expression, + org.eclipse.equinox.internal.p2.metadata.expression.parser, org.eclipse.equinox.internal.p2.query, org.eclipse.equinox.internal.provisional.p2.metadata, org.eclipse.equinox.p2.metadata, + org.eclipse.equinox.p2.metadata.expression, org.eclipse.equinox.p2.metadata.query, org.eclipse.equinox.p2.query, org.eclipse.equinox.p2.repository.artifact, diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/CapabilityIndex.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/CapabilityIndex.java index e6b3f74bf..ccb132be1 100644 --- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/CapabilityIndex.java +++ b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/CapabilityIndex.java @@ -23,34 +23,24 @@ public class CapabilityIndex implements ICapabilityIndex { private final Map<String, Object> capabilityMap; - private static class IUCapability { - final IInstallableUnit iu; - final IProvidedCapability capability; - - IUCapability(IInstallableUnit iu, IProvidedCapability capability) { - this.iu = iu; - this.capability = capability; - } - } - + @SuppressWarnings("unchecked") public CapabilityIndex(Iterator<IInstallableUnit> itor) { HashMap<String, Object> index = new HashMap<String, Object>(); while (itor.hasNext()) { IInstallableUnit iu = itor.next(); Collection<IProvidedCapability> pcs = iu.getProvidedCapabilities(); for (IProvidedCapability pc : pcs) { - IUCapability iuCap = new IUCapability(iu, pc); String name = pc.getName(); - Object prev = index.put(name, iuCap); + Object prev = index.put(name, iu); if (prev != null) { - ArrayList<IUCapability> lst; + ArrayList<IInstallableUnit> lst; if (prev instanceof ArrayList<?>) - lst = (ArrayList<IUCapability>) prev; + lst = (ArrayList<IInstallableUnit>) prev; else { - lst = new ArrayList<IUCapability>(4); - lst.add((IUCapability) prev); + lst = new ArrayList<IInstallableUnit>(4); + lst.add((IInstallableUnit) prev); } - lst.add(iuCap); + lst.add(iu); index.put(name, lst); } } @@ -65,7 +55,7 @@ public class CapabilityIndex implements ICapabilityIndex { List<IInstallableUnit> collector = new ArrayList<IInstallableUnit>(); do { IRequirement nxt = requirements.next(); - collectMatchingIUs((IRequiredCapability) nxt, collector); + collectMatchingIUs(nxt, collector); } while (requirements.hasNext()); return collector.iterator(); } @@ -85,22 +75,22 @@ public class CapabilityIndex implements ICapabilityIndex { private void collectMatchingIUs(IRequirement requirement, Collection<IInstallableUnit> collector) { if (!(requirement instanceof IRequiredCapability)) return; - IRequiredCapability rc = (IRequiredCapability) requirement; - Object v = capabilityMap.get(rc.getName()); + Object v = capabilityMap.get(((IRequiredCapability) requirement).getName()); if (v == null) return; - if (v instanceof IUCapability) { - IUCapability iuc = (IUCapability) v; - if (iuc.capability.satisfies(requirement)) - collector.add(iuc.iu); + if (v instanceof IInstallableUnit) { + IInstallableUnit iu = (IInstallableUnit) v; + if (iu.satisfies(requirement)) + collector.add(iu); } else { - List<IUCapability> iucs = (List<IUCapability>) v; - int idx = iucs.size(); + @SuppressWarnings("unchecked") + List<IInstallableUnit> ius = (List<IInstallableUnit>) v; + int idx = ius.size(); while (--idx >= 0) { - IUCapability iuc = iucs.get(idx); - if (iuc.capability.satisfies(requirement)) - collector.add(iuc.iu); + IInstallableUnit iu = ius.get(idx); + if (iu.satisfies(requirement)) + collector.add(iu); } } } @@ -109,28 +99,28 @@ public class CapabilityIndex implements ICapabilityIndex { if (!(requirement instanceof IRequiredCapability)) return CollectionUtils.emptySet(); - IRequiredCapability rc = (IRequiredCapability) requirement; - Object v = capabilityMap.get(rc.getName()); + Object v = capabilityMap.get(((IRequiredCapability) requirement).getName()); if (v == null) return CollectionUtils.emptySet(); Set<IInstallableUnit> retained = null; - if (v instanceof IUCapability) { - IUCapability iuc = (IUCapability) v; - if (iuc.capability.satisfies(requirement) && collector.contains(iuc.iu)) { + if (v instanceof IInstallableUnit) { + IInstallableUnit iu = (IInstallableUnit) v; + if (iu.satisfies(requirement) && collector.contains(iu)) { if (retained == null) retained = new HashSet<IInstallableUnit>(); - retained.add(iuc.iu); + retained.add(iu); } } else { - List<IUCapability> iucs = (List<IUCapability>) v; - int idx = iucs.size(); + @SuppressWarnings("unchecked") + List<IInstallableUnit> ius = (List<IInstallableUnit>) v; + int idx = ius.size(); while (--idx >= 0) { - IUCapability iuc = iucs.get(idx); - if (iuc.capability.satisfies(requirement) && collector.contains(iuc.iu)) { + IInstallableUnit iu = ius.get(idx); + if (iu.satisfies(requirement) && collector.contains(iu)) { if (retained == null) retained = new HashSet<IInstallableUnit>(); - retained.add(iuc.iu); + retained.add(iu); } } } diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/Everything.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/Everything.java index 4f3fc819b..d127bf72a 100644 --- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/Everything.java +++ b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/Everything.java @@ -10,6 +10,10 @@ *******************************************************************************/ package org.eclipse.equinox.internal.p2.ql; +import org.eclipse.equinox.internal.p2.metadata.expression.IRepeatableIterator; + +import org.eclipse.equinox.internal.p2.metadata.expression.RepeatableIterator; + import java.util.Collection; import java.util.Iterator; import org.eclipse.equinox.internal.p2.core.helpers.CollectionUtils; diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/FlattenIterator.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/FlattenIterator.java index f41e20c1b..179a36613 100644 --- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/FlattenIterator.java +++ b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/FlattenIterator.java @@ -10,6 +10,8 @@ *******************************************************************************/ package org.eclipse.equinox.internal.p2.ql; +import org.eclipse.equinox.internal.p2.metadata.expression.RepeatableIterator; + import java.util.Iterator; import java.util.NoSuchElementException; diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/IRepeatableIterator.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/IRepeatableIterator.java deleted file mode 100644 index 1f8fa8655..000000000 --- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/IRepeatableIterator.java +++ /dev/null @@ -1,25 +0,0 @@ -/******************************************************************************* - * 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; - -import java.util.Iterator; - -public interface IRepeatableIterator<T> extends Iterator<T> { - /** - * Returns a copy that will iterate over the same elements - * as this iterator. The contents or position of this iterator - * is left unchanged. - * @return A re-initialized copy of this iterator. - */ - IRepeatableIterator<T> getCopy(); - - Object getIteratorProvider(); -} diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/MultiVariableContext.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/MultiVariableContext.java deleted file mode 100644 index 8218e76d6..000000000 --- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/MultiVariableContext.java +++ /dev/null @@ -1,51 +0,0 @@ -/******************************************************************************* - * 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; - -import org.eclipse.equinox.p2.ql.IEvaluationContext; -import org.eclipse.equinox.p2.ql.IExpression; - -public final class MultiVariableContext implements IEvaluationContext { - private final IEvaluationContext parentContext; - - private final Object[] values; - - public MultiVariableContext(IEvaluationContext parentContext, IExpression[] variables) { - this.parentContext = parentContext; - values = new Object[variables.length * 2]; - for (int idx = 0, ndx = 0; ndx < variables.length; ++ndx, idx += 2) - values[idx] = variables[ndx]; - } - - public Object getParameter(int position) { - return parentContext.getParameter(position); - } - - public Object getParameter(String key) { - return parentContext.getParameter(key); - } - - public Object getValue(IExpression variable) { - for (int idx = 0; idx < values.length; ++idx) - if (values[idx++] == variable) - return values[idx]; - return parentContext.getValue(variable); - } - - public void setValue(IExpression variable, Object value) { - for (int idx = 0; idx < values.length; ++idx) - if (values[idx++] == variable) { - values[idx] = value; - return; - } - parentContext.setValue(variable, value); - } -}
\ No newline at end of file diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/ParameterContext.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/ParameterContext.java deleted file mode 100644 index 653c103ad..000000000 --- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/ParameterContext.java +++ /dev/null @@ -1,44 +0,0 @@ -/******************************************************************************* - * 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; - -import java.util.Map; -import org.eclipse.equinox.p2.ql.IEvaluationContext; -import org.eclipse.equinox.p2.ql.IExpression; - -/** - * The immutable top level context used when evaluating an expression. - */ -public final class ParameterContext implements IEvaluationContext { - private static final Object[] noParameters = new Object[0]; - - private final Object[] parameters; - - public ParameterContext(Object[] parameters) { - this.parameters = parameters == null ? noParameters : parameters; - } - - public Object getParameter(int position) { - return parameters[position]; - } - - public Object getParameter(String key) { - return parameters.length == 1 && parameters[0] instanceof Map<?, ?> ? ((Map<?, ?>) parameters[0]).get(key) : null; - } - - public Object getValue(IExpression variable) { - throw new IllegalArgumentException("No such variable: " + variable); //$NON-NLS-1$ - } - - public void setValue(IExpression variable, Object value) { - throw new IllegalArgumentException("No such variable: " + variable); //$NON-NLS-1$ - } -} diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/QueryContext.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/QueryContext.java index 2f82b3f25..0f8f63cf2 100644 --- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/QueryContext.java +++ b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/QueryContext.java @@ -3,6 +3,8 @@ package org.eclipse.equinox.internal.p2.ql; import java.util.*; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.equinox.internal.p2.metadata.expression.IRepeatableIterator; +import org.eclipse.equinox.internal.p2.metadata.expression.RepeatableIterator; import org.eclipse.equinox.p2.metadata.IInstallableUnit; import org.eclipse.equinox.p2.ql.IQueryContext; import org.eclipse.equinox.p2.ql.ITranslationSupport; diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/RepeatableIterator.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/RepeatableIterator.java deleted file mode 100644 index 7c1a83500..000000000 --- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/RepeatableIterator.java +++ /dev/null @@ -1,237 +0,0 @@ -/******************************************************************************* - * 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; - -import java.util.*; -import org.eclipse.equinox.p2.query.IQueryResult; - -public class RepeatableIterator<T> implements IRepeatableIterator<T> { - private final List<T> values; - private int position = -1; - - @SuppressWarnings("unchecked") - public static <T> IRepeatableIterator<T> create(Object unknown) { - if (unknown.getClass().isArray()) - return create((T[]) unknown); - if (unknown instanceof Iterator<?>) - return create((Iterator<T>) unknown); - if (unknown instanceof List<?>) - return create((List<T>) unknown); - if (unknown instanceof Collection<?>) - return create((Collection<T>) unknown); - if (unknown instanceof Map<?, ?>) - return create((Set<T>) ((Map<?, ?>) unknown).entrySet()); - if (unknown instanceof IQueryResult<?>) - return create((IQueryResult<T>) unknown); - throw new IllegalArgumentException("Cannot convert a " + unknown.getClass().getName() + " into an iterator"); //$NON-NLS-1$ //$NON-NLS-2$ - } - - public static <T> IRepeatableIterator<T> create(Iterator<T> iterator) { - return iterator instanceof IRepeatableIterator<?> ? ((IRepeatableIterator<T>) iterator).getCopy() : new ElementRetainingIterator<T>(iterator); - } - - public static <T> IRepeatableIterator<T> create(List<T> values) { - return new RepeatableIterator<T>(values); - } - - public static <T> IRepeatableIterator<T> create(Collection<T> values) { - return new CollectionIterator<T>(values); - } - - public static <T> IRepeatableIterator<T> create(IQueryResult<T> values) { - return new QueryResultIterator<T>(values); - } - - public static <T> IRepeatableIterator<T> create(T[] values) { - return new ArrayIterator<T>(values); - } - - RepeatableIterator(List<T> values) { - this.values = values; - } - - public IRepeatableIterator<T> getCopy() { - return new RepeatableIterator<T>(values); - } - - public boolean hasNext() { - return position + 1 < values.size(); - } - - public T next() { - if (++position == values.size()) { - --position; - throw new NoSuchElementException(); - } - return values.get(position); - } - - public void remove() { - throw new UnsupportedOperationException(); - } - - public Object getIteratorProvider() { - return values; - } - - void setPosition(int position) { - this.position = position; - } - - List<T> getValues() { - return values; - } - - static class ArrayIterator<T> implements IRepeatableIterator<T> { - private final T[] array; - private int position = -1; - - public ArrayIterator(T[] array) { - this.array = array; - } - - public Object getIteratorProvider() { - return array; - } - - public boolean hasNext() { - return position + 1 < array.length; - } - - public T next() { - if (++position >= array.length) - throw new NoSuchElementException(); - return array[position]; - } - - public void remove() { - throw new UnsupportedOperationException(); - } - - public IRepeatableIterator<T> getCopy() { - return new ArrayIterator<T>(array); - } - } - - static class CollectionIterator<T> implements IRepeatableIterator<T> { - private final Collection<T> collection; - - private final Iterator<T> iterator; - - CollectionIterator(Collection<T> collection) { - this.collection = collection; - this.iterator = collection.iterator(); - } - - public IRepeatableIterator<T> getCopy() { - return new CollectionIterator<T>(collection); - } - - public Object getIteratorProvider() { - return collection; - } - - public boolean hasNext() { - return iterator.hasNext(); - } - - public T next() { - return iterator.next(); - } - - public void remove() { - throw new UnsupportedOperationException(); - } - } - - static class QueryResultIterator<T> implements IRepeatableIterator<T> { - private final IQueryResult<T> queryResult; - - private final Iterator<T> iterator; - - QueryResultIterator(IQueryResult<T> queryResult) { - this.queryResult = queryResult; - this.iterator = queryResult.iterator(); - } - - public IRepeatableIterator<T> getCopy() { - return new QueryResultIterator<T>(queryResult); - } - - public Object getIteratorProvider() { - return queryResult; - } - - public boolean hasNext() { - return iterator.hasNext(); - } - - public T next() { - return iterator.next(); - } - - public void remove() { - throw new UnsupportedOperationException(); - } - } - - static class ElementRetainingIterator<T> extends RepeatableIterator<T> { - - private Iterator<T> innerIterator; - - ElementRetainingIterator(Iterator<T> iterator) { - super(new ArrayList<T>()); - innerIterator = iterator; - } - - public synchronized boolean hasNext() { - if (innerIterator != null) { - if (innerIterator.hasNext()) - return true; - innerIterator = null; - setPosition(getValues().size()); - } - return super.hasNext(); - } - - public synchronized T next() { - if (innerIterator != null) { - T val = innerIterator.next(); - getValues().add(val); - return val; - } - return super.next(); - } - - public synchronized IRepeatableIterator<T> getCopy() { - // If the current iterator still exists, we must exhaust it first - // - exhaustInnerIterator(); - return super.getCopy(); - } - - public synchronized Object getIteratorProvider() { - exhaustInnerIterator(); - return super.getIteratorProvider(); - } - - private void exhaustInnerIterator() { - if (innerIterator != null) { - List<T> values = getValues(); - int savePos = values.size() - 1; - while (innerIterator.hasNext()) - values.add(innerIterator.next()); - innerIterator = null; - setPosition(savePos); - } - } - } -} diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/SingleVariableContext.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/SingleVariableContext.java deleted file mode 100644 index 5d57b69c3..000000000 --- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/SingleVariableContext.java +++ /dev/null @@ -1,46 +0,0 @@ -/******************************************************************************* - * 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; - -import org.eclipse.equinox.p2.ql.IEvaluationContext; -import org.eclipse.equinox.p2.ql.IExpression; - -public final class SingleVariableContext implements IEvaluationContext { - private final IEvaluationContext parentContext; - - private Object value; - - private final IExpression variable; - - public SingleVariableContext(IEvaluationContext parentContext, IExpression variable) { - this.parentContext = parentContext; - this.variable = variable; - } - - public Object getParameter(int position) { - return parentContext.getParameter(position); - } - - public Object getParameter(String key) { - return parentContext.getParameter(key); - } - - public Object getValue(IExpression var) { - return variable == var ? value : parentContext.getValue(var); - } - - public void setValue(IExpression var, Object val) { - if (variable == var) - value = val; - else - parentContext.setValue(var, val); - } -}
\ No newline at end of file diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/All.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/All.java deleted file mode 100644 index a8181dc2c..000000000 --- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/All.java +++ /dev/null @@ -1,46 +0,0 @@ -/******************************************************************************* - * 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.Iterator; -import org.eclipse.equinox.p2.ql.IEvaluationContext; - -/** - * A collection filter that yields true if the <code>filter</code> yields true for - * all of the elements of the <code>collection</code> - */ -final class All extends CollectionFilter { - All(Expression collection, LambdaExpression lambda) { - super(collection, lambda); - } - - public int getExpressionType() { - return TYPE_ALL; - } - - Object evaluate(IEvaluationContext context, Iterator<?> itor) { - Variable variable = lambda.getItemVariable(); - while (itor.hasNext()) { - variable.setValue(context, itor.next()); - if (lambda.evaluate(context) != Boolean.TRUE) - return Boolean.FALSE; - } - return Boolean.TRUE; - } - - String getOperator() { - return KEYWORD_ALL; - } - - boolean isBoolean() { - return true; - } -} diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/And.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/And.java deleted file mode 100644 index 992ad9be5..000000000 --- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/And.java +++ /dev/null @@ -1,73 +0,0 @@ -/******************************************************************************* - * 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.*; -import org.eclipse.equinox.p2.ql.IEvaluationContext; - -/** - * n-ary AND operator. This operator evaluates its first operand and then checks - * the class of the result. If the class is {@link Boolean} then it is assumed - * that all other operands also evaluates to a boolean and the full evaluation is - * <code>true</code> if all its operands evaluate to <code>true</code>. If the first - * result was not of class {@link Boolean}, then it is assumed that it can be accessed - * as an {@link Iterator} and that all other operands also evaluates to something that - * can be accessed as an {@link Iterator}. The AND operator will then function as a - * INTERSECT operator and the result is the set of elements that were found in all operands. - */ -final class And extends NAry { - And(Expression[] operands) { - super(assertLength(operands, 2, OPERATOR_AND)); - } - - public Object evaluate(IEvaluationContext context) { - Object firstValue = operands[0].evaluate(context); - - // Determine operation mode - if (firstValue instanceof Boolean) { - // The first value was boolean. Assume that the rest are too - if (!((Boolean) firstValue).booleanValue()) - return Boolean.FALSE; - - for (int idx = 1; idx < operands.length; ++idx) { - if (operands[idx].evaluate(context) != Boolean.TRUE) - return Boolean.FALSE; - } - return Boolean.TRUE; - } - - // Not a boolean. Assume that we can use an iterator on all values - Set<?> resultSet = asSet(firstValue, false); // Safe since it will not be modified - for (int idx = 1; idx < operands.length && !resultSet.isEmpty(); ++idx) { - Iterator<?> itor = operands[idx].evaluateAsIterator(context); - Set<Object> retained = new HashSet<Object>(); - while (itor.hasNext()) { - Object value = itor.next(); - if (resultSet.contains(value)) - retained.add(value); - } - resultSet = retained; - } - return resultSet; - } - - public int getExpressionType() { - return TYPE_AND; - } - - String getOperator() { - return OPERATOR_AND; - } - - int getPriority() { - return PRIORITY_AND; - } -} diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Array.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Array.java index ebba0e5ca..62dfb329c 100644 --- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Array.java +++ b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Array.java @@ -12,13 +12,14 @@ package org.eclipse.equinox.internal.p2.ql.expression; import java.util.Iterator; import java.util.NoSuchElementException; -import org.eclipse.equinox.internal.p2.ql.parser.IParserConstants; -import org.eclipse.equinox.p2.ql.IEvaluationContext; +import org.eclipse.equinox.internal.p2.metadata.expression.*; +import org.eclipse.equinox.p2.metadata.expression.IEvaluationContext; +import org.eclipse.equinox.p2.ql.IQLExpression; /** * An array of expressions */ -final class Array extends NAry { +final class Array extends NAry implements IQLConstants, IQLExpression { final class ArrayIterator implements Iterator<Object> { private final IEvaluationContext context; @@ -45,19 +46,8 @@ final class Array extends NAry { } } - static void elementsToString(StringBuffer bld, Expression[] elements) { - int top = elements.length; - if (top > 0) { - elements[0].toString(bld); - for (int idx = 1; idx < top; ++idx) { - bld.append(", "); //$NON-NLS-1$ - appendOperand(bld, elements[idx], PRIORITY_COMMA); - } - } - } - Array(Expression[] operands) { - super(assertLength(operands, 0, IParserConstants.OPERATOR_ARRAY)); + super(assertLength(operands, 0, OPERATOR_ARRAY)); } public Object evaluate(IEvaluationContext context) { @@ -72,29 +62,17 @@ final class Array extends NAry { return TYPE_ARRAY; } - public void toString(StringBuffer bld) { + public void toString(StringBuffer bld, Variable rootVariable) { bld.append('['); - elementsToString(bld, operands); + elementsToString(bld, rootVariable, operands); bld.append(']'); } - String getOperator() { - return IParserConstants.OPERATOR_ARRAY; - } - - int getPriority() { - return PRIORITY_CONSTRUCTOR; - } - - boolean isBoolean() { - return false; - } - - boolean isCollection() { - return true; + public String getOperator() { + return OPERATOR_ARRAY; } - boolean isElementBoolean() { - return super.isBoolean(); + public int getPriority() { + return PRIORITY_FUNCTION; } } diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Assignment.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Assignment.java index 23b69e8a7..22b747b7e 100644 --- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Assignment.java +++ b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Assignment.java @@ -10,12 +10,15 @@ *******************************************************************************/ package org.eclipse.equinox.internal.p2.ql.expression; -import org.eclipse.equinox.p2.ql.IEvaluationContext; +import java.util.Iterator; +import org.eclipse.equinox.internal.p2.metadata.expression.*; +import org.eclipse.equinox.p2.metadata.expression.IEvaluationContext; +import org.eclipse.equinox.p2.ql.IQLExpression; /** * An expression representing a variable stack in the current thread. */ -class Assignment extends Binary { +class Assignment extends Binary implements IQLConstants, IQLExpression { Assignment(Variable variable, Expression expression) { super(variable, expression); } @@ -30,19 +33,17 @@ class Assignment extends Binary { return TYPE_ASSIGNMENT; } - int getPriority() { - return PRIORITY_ASSIGNMENT; + public int getPriority() { + return IExpressionConstants.PRIORITY_ASSIGNMENT; } - String getOperator() { + public String getOperator() { return OPERATOR_ASSIGN; } - boolean isBoolean() { - return rhs.isBoolean(); - } - - boolean isCollection() { - return rhs.isCollection(); + public Iterator<?> evaluateAsIterator(IEvaluationContext context) { + Iterator<?> value = rhs.evaluateAsIterator(context); + context.setValue(lhs, value); + return value; } } diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/At.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/At.java index 70b97119f..70d1639f9 100644 --- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/At.java +++ b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/At.java @@ -10,76 +10,30 @@ *******************************************************************************/ package org.eclipse.equinox.internal.p2.ql.expression; -import java.util.*; -import org.eclipse.equinox.internal.p2.ql.expression.Member.DynamicMember; +import org.eclipse.equinox.internal.p2.metadata.expression.Expression; +import org.eclipse.equinox.internal.p2.metadata.expression.Member; import org.eclipse.equinox.p2.metadata.IInstallableUnit; -import org.eclipse.equinox.p2.ql.IEvaluationContext; +import org.eclipse.equinox.p2.metadata.expression.IEvaluationContext; +import org.eclipse.equinox.p2.ql.IQLExpression; import org.eclipse.equinox.p2.ql.ITranslationSupport; /** * This class represents indexed or keyed access to an indexed collection * or a map. */ -final class At extends Binary { +final class At extends org.eclipse.equinox.internal.p2.metadata.expression.At implements IQLExpression { At(Expression lhs, Expression rhs) { super(lhs, rhs); } - public Object evaluate(IEvaluationContext context) { - Object lval; - if (lhs instanceof DynamicMember) { - DynamicMember lm = (DynamicMember) lhs; - Object instance = lm.operand.evaluate(context); - if (instance instanceof IInstallableUnit) { - if ("properties".equals(lm.name)) //$NON-NLS-1$ - // Avoid full copy of the properties map just to get one member - return ((IInstallableUnit) instance).getProperty((String) rhs.evaluate(context)); - - if (VARIABLE_TRANSLATIONS.equals(lm.name)) { - ITranslationSupport ts = (ITranslationSupport) Variable.TRANSLATIONS.evaluate(context); - return ts.getIUProperty((IInstallableUnit) instance, (String) rhs.evaluate(context)); - } + protected Object handleMember(IEvaluationContext context, Member member, Object instance, boolean[] handled) { + if (instance instanceof IInstallableUnit) { + if (IQLConstants.VARIABLE_TRANSLATIONS.equals(member.getName())) { + ITranslationSupport ts = (ITranslationSupport) QLFactory.TRANSLATIONS.evaluate(context); + handled[0] = true; + return ts.getIUProperty((IInstallableUnit) instance, (String) rhs.evaluate(context)); } - lval = lm.invoke(instance); - } else - lval = lhs.evaluate(context); - - Object rval = rhs.evaluate(context); - if (lval == null) - throw new IllegalArgumentException("Unable to use [] on null"); //$NON-NLS-1$ - - if (lval instanceof Map<?, ?>) - return ((Map<?, ?>) lval).get(rval); - - if (rval instanceof Number) { - if (lval instanceof List<?>) - return ((List<?>) lval).get(((Number) rval).intValue()); - if (lval != null && lval.getClass().isArray()) - return ((Object[]) lval)[((Number) rval).intValue()]; } - - if (lval instanceof Dictionary<?, ?>) - return ((Dictionary<?, ?>) lval).get(rval); - - throw new IllegalArgumentException("Unable to use [] on a " + lval.getClass().getName()); //$NON-NLS-1$ - } - - public int getExpressionType() { - return TYPE_AT; - } - - public void toString(StringBuffer bld) { - appendOperand(bld, lhs, getPriority()); - bld.append('['); - appendOperand(bld, rhs, PRIORITY_COMMA); - bld.append(']'); - } - - String getOperator() { - return OPERATOR_AT; - } - - int getPriority() { - return PRIORITY_MEMBER; + return super.handleMember(context, member, instance, handled); } } diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Binary.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Binary.java deleted file mode 100644 index ac17e0d49..000000000 --- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Binary.java +++ /dev/null @@ -1,47 +0,0 @@ -/******************************************************************************* - * 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 org.eclipse.equinox.p2.ql.IExpressionVisitor; - -/** - * The abstract base class for all binary operations - */ -abstract class Binary extends Expression { - final Expression lhs; - - final Expression rhs; - - Binary(Expression lhs, Expression rhs) { - this.lhs = lhs; - this.rhs = rhs; - } - - public boolean accept(IExpressionVisitor visitor) { - return super.accept(visitor) && lhs.accept(visitor) && rhs.accept(visitor); - } - - public void toString(StringBuffer bld) { - appendOperand(bld, lhs, getPriority()); - bld.append(' '); - bld.append(getOperator()); - bld.append(' '); - appendOperand(bld, rhs, getPriority()); - } - - int countReferenceToEverything() { - return lhs.countReferenceToEverything() + rhs.countReferenceToEverything(); - } - - int getPriority() { - return PRIORITY_BINARY; // Default priority - } -} diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/BooleanFunction.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/BooleanFunction.java index 10268eb36..860fe6e12 100644 --- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/BooleanFunction.java +++ b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/BooleanFunction.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009 Cloudsmith Inc. and others. + * 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 @@ -10,14 +10,15 @@ *******************************************************************************/ package org.eclipse.equinox.internal.p2.ql.expression; +import org.eclipse.equinox.internal.p2.metadata.expression.Expression; + /** * A function that obtains a class based on a String */ -final class BooleanFunction extends Function { +public final class BooleanFunction extends Function { public BooleanFunction(Expression[] operands) { super(assertLength(operands, 1, 1, KEYWORD_BOOLEAN)); - assertNotCollection(operands[0], "parameter"); //$NON-NLS-1$ } boolean assertSingleArgumentClass(Object v) { @@ -32,7 +33,7 @@ final class BooleanFunction extends Function { return Boolean.FALSE; } - String getOperator() { + public String getOperator() { return KEYWORD_BOOLEAN; } } diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/CapabilityIndexFunction.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/CapabilityIndexFunction.java index 99e37e985..56297974e 100644 --- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/CapabilityIndexFunction.java +++ b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/CapabilityIndexFunction.java @@ -11,26 +11,75 @@ package org.eclipse.equinox.internal.p2.ql.expression; import java.util.Iterator; +import org.eclipse.equinox.internal.p2.metadata.expression.Expression; +import org.eclipse.equinox.internal.p2.metadata.expression.Member; import org.eclipse.equinox.internal.p2.ql.CapabilityIndex; import org.eclipse.equinox.p2.metadata.IInstallableUnit; -import org.eclipse.equinox.p2.ql.IEvaluationContext; +import org.eclipse.equinox.p2.metadata.IRequirement; +import org.eclipse.equinox.p2.metadata.expression.IEvaluationContext; +import org.eclipse.equinox.p2.ql.ICapabilityIndex; +import org.eclipse.equinox.p2.ql.IQLExpression; /** * A function that creates a {@link CapabilityIndex} based on a collection of * {@link IInstallableUnit} instances. */ -final class CapabilityIndexFunction extends Function { +public final class CapabilityIndexFunction extends Function implements IQLConstants { + static abstract class CapabilityIndexMethod extends Member implements IQLExpression { + public CapabilityIndexMethod(Expression operand, String name, Expression[] args) { + super(operand, name, args); + } + + final ICapabilityIndex getSelf(IEvaluationContext context) { + Object self = operand.evaluate(context); + if (self instanceof ICapabilityIndex) + return (ICapabilityIndex) self; + throw new IllegalArgumentException("lhs of member expected to be an ICapabilityIndex implementation"); //$NON-NLS-1$ + } + + public final Object evaluate(IEvaluationContext context) { + return evaluateAsIterator(context); + } + + boolean isCollection() { + return true; + } + } + + static final class SatisfiesAny extends CapabilityIndexMethod { + + public SatisfiesAny(Expression operand, Expression[] argExpressions) { + super(operand, KEYWORD_SATISFIES_ANY, assertLength(argExpressions, 1, 1, KEYWORD_SATISFIES_ANY)); + } + + @SuppressWarnings("unchecked") + public Iterator<?> evaluateAsIterator(IEvaluationContext context) { + return getSelf(context).satisfiesAny((Iterator<IRequirement>) argExpressions[0].evaluateAsIterator(context)); + } + } + + static final class SatisfiesAll extends CapabilityIndexMethod { + + public SatisfiesAll(Expression operand, Expression[] argExpressions) { + super(operand, KEYWORD_SATISFIES_ALL, assertLength(argExpressions, 1, 1, KEYWORD_SATISFIES_ALL)); + } + + @SuppressWarnings("unchecked") + public Iterator<?> evaluateAsIterator(IEvaluationContext context) { + return getSelf(context).satisfiesAll((Iterator<IRequirement>) argExpressions[0].evaluateAsIterator(context)); + } + } public CapabilityIndexFunction(Expression[] operands) { super(assertLength(operands, 1, 1, KEYWORD_CAPABILITY_INDEX)); - assertNotBoolean(operands[0], "parameter"); //$NON-NLS-1$ } + @SuppressWarnings("unchecked") public Object evaluate(IEvaluationContext context) { return new CapabilityIndex((Iterator<IInstallableUnit>) operands[0].evaluateAsIterator(context)); } - String getOperator() { + public String getOperator() { return KEYWORD_CAPABILITY_INDEX; } } diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/ClassFunction.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/ClassFunction.java index 5fe40c0ac..53d0b3044 100644 --- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/ClassFunction.java +++ b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/ClassFunction.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009 Cloudsmith Inc. and others. + * 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 @@ -10,15 +10,15 @@ *******************************************************************************/ package org.eclipse.equinox.internal.p2.ql.expression; +import org.eclipse.equinox.internal.p2.metadata.expression.Expression; + /** * A function that obtains a class based on a String */ -final class ClassFunction extends Function { +public final class ClassFunction extends Function { public ClassFunction(Expression[] operands) { super(assertLength(operands, 1, 1, KEYWORD_CLASS)); - assertNotBoolean(operands[0], "parameter"); //$NON-NLS-1$ - assertNotCollection(operands[0], "parameter"); //$NON-NLS-1$ } boolean assertSingleArgumentClass(Object v) { @@ -33,7 +33,7 @@ final class ClassFunction extends Function { } } - String getOperator() { + public String getOperator() { return KEYWORD_CLASS; } } diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Collect.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Collect.java index fddda5dd5..5f3a67ebc 100644 --- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Collect.java +++ b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Collect.java @@ -11,12 +11,14 @@ package org.eclipse.equinox.internal.p2.ql.expression; import java.util.Iterator; -import org.eclipse.equinox.p2.ql.IEvaluationContext; -import org.eclipse.equinox.p2.ql.IExpression; +import org.eclipse.equinox.internal.p2.metadata.expression.*; +import org.eclipse.equinox.p2.metadata.expression.IEvaluationContext; +import org.eclipse.equinox.p2.metadata.expression.IExpression; +import org.eclipse.equinox.p2.ql.IQLExpression; /** */ -final class Collect extends CollectionFilter { +final class Collect extends CollectionFilter implements IQLExpression { final class CollectIterator implements Iterator<Object> { private final IEvaluationContext context; @@ -48,11 +50,11 @@ final class Collect extends CollectionFilter { super(collection, lambda); } - Object evaluate(IEvaluationContext context, Iterator<?> itor) { + public Object evaluate(IEvaluationContext context, Iterator<?> itor) { return evaluateAsIterator(context, itor); } - Iterator<?> evaluateAsIterator(IEvaluationContext context, Iterator<?> itor) { + public Iterator<?> evaluateAsIterator(IEvaluationContext context, Iterator<?> itor) { return new CollectIterator(context, itor); } @@ -60,11 +62,7 @@ final class Collect extends CollectionFilter { return TYPE_COLLECT; } - String getOperator() { - return KEYWORD_COLLECT; - } - - boolean isCollection() { - return true; + public String getOperator() { + return IQLConstants.KEYWORD_COLLECT; } } diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/CollectionFilter.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/CollectionFilter.java deleted file mode 100644 index b33b28aee..000000000 --- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/CollectionFilter.java +++ /dev/null @@ -1,73 +0,0 @@ -/******************************************************************************* - * 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.Iterator; -import org.eclipse.equinox.p2.ql.IEvaluationContext; -import org.eclipse.equinox.p2.ql.IExpressionVisitor; - -/** - * Some kind of operation that is performed for each element of a collection. I.e. - * <code>x.<operation>(y | <expression&rt;)</code> - */ -abstract class CollectionFilter extends Unary { - static void appendProlog(StringBuffer bld, Expression lhs, String operator) { - if (lhs != Variable.EVERYTHING && lhs != Variable.ITEM) { - appendOperand(bld, lhs, PRIORITY_COLLECTION); - bld.append('.'); - } - bld.append(operator); - bld.append('('); - } - - final LambdaExpression lambda; - - CollectionFilter(Expression collection, LambdaExpression lambda) { - super(collection); - this.lambda = lambda; - } - - public boolean accept(IExpressionVisitor visitor) { - return super.accept(visitor) && lambda.accept(visitor); - } - - public final Object evaluate(IEvaluationContext context) { - Iterator<?> lval = operand.evaluateAsIterator(context); - context = lambda.prolog(context); - return evaluate(context, lval); - } - - public final Iterator<?> evaluateAsIterator(IEvaluationContext context) { - Iterator<?> lval = operand.evaluateAsIterator(context); - context = lambda.prolog(context); - return evaluateAsIterator(context, lval); - } - - public void toString(StringBuffer bld) { - appendProlog(bld, operand, getOperator()); - appendOperand(bld, lambda, PRIORITY_LAMBDA); - bld.append(')'); - } - - int countReferenceToEverything() { - return super.countReferenceToEverything() + lambda.countReferenceToEverything(); - } - - abstract Object evaluate(final IEvaluationContext context, Iterator<?> iterator); - - Iterator<?> evaluateAsIterator(IEvaluationContext context, Iterator<?> iterator) { - throw new UnsupportedOperationException(); - } - - int getPriority() { - return PRIORITY_COLLECTION; - } -} diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Compare.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Compare.java deleted file mode 100644 index 89d21d02e..000000000 --- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Compare.java +++ /dev/null @@ -1,71 +0,0 @@ -/******************************************************************************* - * 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 org.eclipse.equinox.p2.metadata.Version; -import org.eclipse.equinox.p2.ql.IEvaluationContext; - -/** - * Comparisons for magnitude. - */ -final class Compare extends Binary { - final boolean compareLess; - final boolean equalOK; - - Compare(Expression lhs, Expression rhs, boolean compareLess, boolean equalOK) { - super(lhs, rhs); - this.compareLess = compareLess; - this.equalOK = equalOK; - assertNotCollection(lhs, "lhs"); //$NON-NLS-1$ - assertNotCollection(rhs, "rhs"); //$NON-NLS-1$ - } - - public Object evaluate(IEvaluationContext context) { - Object lval = lhs.evaluate(context); - Object rval = rhs.evaluate(context); - if (lval == null || rval == null) - throw new IllegalArgumentException("Cannot compare null to anything"); //$NON-NLS-1$ - - try { - - if (lval.getClass() != rval.getClass()) { - if (lval instanceof Version && rval instanceof String) - rval = Version.create((String) rval); - else if (rval instanceof Version && lval instanceof String) - lval = Version.create((String) lval); - else if (lval instanceof String) - rval = rval.toString(); - else if (rval instanceof String) - lval = lval.toString(); - } - - if (lval instanceof Comparable) { - int cmpResult = ((Comparable) lval).compareTo(rval); - return Boolean.valueOf(cmpResult == 0 ? equalOK : (cmpResult < 0 ? compareLess : !compareLess)); - } - } catch (Exception e) { - // - } - throw new IllegalArgumentException("Cannot compare a " + lval.getClass().getName() + " to a " + rval.getClass().getName()); //$NON-NLS-1$//$NON-NLS-2$ - } - - public int getExpressionType() { - return compareLess ? (equalOK ? TYPE_LESS_EQUAL : TYPE_LESS) : (equalOK ? TYPE_GREATER_EQUAL : TYPE_GREATER); - } - - String getOperator() { - return compareLess ? (equalOK ? OPERATOR_LT_EQUAL : OPERATOR_LT) : (equalOK ? OPERATOR_GT_EQUAL : OPERATOR_GT); - } - - boolean isBoolean() { - return true; - } -} diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Condition.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Condition.java index 543294be4..9de25672c 100644 --- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Condition.java +++ b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Condition.java @@ -10,49 +10,55 @@ *******************************************************************************/ package org.eclipse.equinox.internal.p2.ql.expression; -import org.eclipse.equinox.p2.ql.IEvaluationContext; +import java.util.Iterator; +import org.eclipse.equinox.internal.p2.metadata.expression.*; +import org.eclipse.equinox.p2.metadata.expression.IEvaluationContext; +import org.eclipse.equinox.p2.ql.IQLExpression; /** * Comparisons for magnitude. */ -final class Condition extends Binary { +final class Condition extends Binary implements IQLConstants, IQLExpression { final Expression ifFalse; Condition(Expression test, Expression ifTrue, Expression ifFalse) { super(test, ifTrue); this.ifFalse = ifFalse; - assertNotCollection(test, "test"); //$NON-NLS-1$ + } + + public boolean equals(Object o) { + return super.equals(o) && ifFalse.equals(((Condition) o).ifFalse); } public Object evaluate(IEvaluationContext context) { return lhs.evaluate(context) == Boolean.TRUE ? rhs.evaluate(context) : ifFalse.evaluate(context); } - public int getExpressionType() { - return TYPE_CONDITION; + public Iterator<?> evaluateAsIterator(IEvaluationContext context) { + return lhs.evaluate(context) == Boolean.TRUE ? rhs.evaluateAsIterator(context) : ifFalse.evaluateAsIterator(context); + } + + public int hashCode() { + return super.hashCode() * 31 + ifFalse.hashCode(); } - public void toString(StringBuffer bld) { - super.toString(bld); + public void toString(StringBuffer bld, Variable rootVariable) { + super.toString(bld, rootVariable); bld.append(' '); bld.append(OPERATOR_ELSE); bld.append(' '); - appendOperand(bld, ifFalse, getPriority()); + appendOperand(bld, rootVariable, ifFalse, getPriority()); } - String getOperator() { - return OPERATOR_IF; - } - - int getPriority() { - return PRIORITY_CONDITION; + public int getExpressionType() { + return TYPE_CONDITION; } - boolean isBoolean() { - return rhs.isBoolean() && ifFalse.isBoolean(); + public String getOperator() { + return OPERATOR_IF; } - boolean isCollection() { - return rhs.isCollection() && ifFalse.isCollection(); + public int getPriority() { + return IExpressionConstants.PRIORITY_CONDITION; } } diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Constant.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Constant.java deleted file mode 100644 index 797f04535..000000000 --- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Constant.java +++ /dev/null @@ -1,94 +0,0 @@ -/******************************************************************************* - * 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.*; -import org.eclipse.equinox.p2.ql.IEvaluationContext; -import org.eclipse.equinox.p2.ql.SimplePattern; -import org.eclipse.equinox.p2.query.IQueryResult; - -/** - * An expression that represents a constant value. - */ -final class Constant extends Expression { - private final Object value; - - static final Constant NULL_CONSTANT = new Constant(null); - - static final Constant TRUE_CONSTANT = new Constant(Boolean.TRUE); - - static final Constant FALSE_CONSTANT = new Constant(Boolean.FALSE); - - static Constant create(Object value) { - if (value == null) - return NULL_CONSTANT; - if (value == Boolean.TRUE) - return TRUE_CONSTANT; - if (value == Boolean.FALSE) - return FALSE_CONSTANT; - return new Constant(value); - } - - private Constant(Object value) { - this.value = value; - } - - public Object evaluate(IEvaluationContext context) { - return value; - } - - public int getExpressionType() { - return TYPE_LITERAL; - } - - public void toString(StringBuffer bld) { - if (value == null) - bld.append("null"); //$NON-NLS-1$ - else if (value instanceof String) { - String str = (String) value; - char sep = str.indexOf('\'') >= 0 ? '"' : '\''; - bld.append(sep); - bld.append(str); - bld.append(sep); - } else if (value instanceof SimplePattern) { - appendEscaped(bld, '/', value.toString()); - } else - bld.append(value); - } - - int getPriority() { - return PRIORITY_LITERAL; - } - - private void appendEscaped(StringBuffer bld, char delimiter, String str) { - bld.append(delimiter); - int top = str.length(); - for (int idx = 0; idx < top; ++idx) { - char c = str.charAt(idx); - if (c == delimiter) - bld.append('\\'); - bld.append(c); - } - bld.append(delimiter); - } - - boolean isBoolean() { - return value instanceof Boolean; - } - - boolean isCollection() { - return value instanceof Collection<?> || value instanceof Map<?, ?> || value instanceof Iterator<?> || value instanceof IQueryResult<?> || value != null && value.getClass().isArray(); - } - - String getOperator() { - return "<literal>"; //$NON-NLS-1$ - } -} diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/ContextExpression.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/ContextExpression.java index 031eb5017..26cbce481 100644 --- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/ContextExpression.java +++ b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/ContextExpression.java @@ -11,37 +11,49 @@ package org.eclipse.equinox.internal.p2.ql.expression; import java.util.Iterator; -import org.eclipse.equinox.internal.p2.ql.*; -import org.eclipse.equinox.p2.ql.*; +import org.eclipse.equinox.internal.p2.metadata.expression.*; +import org.eclipse.equinox.internal.p2.ql.Everything; +import org.eclipse.equinox.p2.metadata.expression.*; +import org.eclipse.equinox.p2.ql.IContextExpression; +import org.eclipse.equinox.p2.ql.ITranslationSupport; /** * The context expression is the top expression in context queries. It introduces the * variable 'everything' and initialized it with the iterator that represents all * available items. */ -final class ContextExpression<T> extends Unary implements IContextExpression<T> { - +public final class ContextExpression<T> extends Unary implements IContextExpression<T>, IQLConstants { + private static final Object[] noParams = new Object[0]; private final Class<T> elementClass; + private final Object[] parameters; - ContextExpression(Class<T> elementClass, Expression expression) { + public ContextExpression(Class<T> elementClass, Expression expression, Object[] parameters) { super(expression); this.elementClass = elementClass; + this.parameters = parameters == null ? noParams : parameters; } - public void toString(StringBuffer bld) { - operand.toString(bld); + public boolean accept(IExpressionVisitor visitor) { + return visitor.visit(operand); + } + + public void toString(StringBuffer bld, Variable rootVariable) { + operand.toString(bld, rootVariable); } - public IEvaluationContext createContext(Iterator<T> iterator, Object[] params) { - IEvaluationContext context = new SingleVariableContext(new ParameterContext(params), Variable.EVERYTHING); - context.setValue(Variable.EVERYTHING, new Everything<T>(elementClass, iterator, operand.needsRepeatedIterations())); + public IEvaluationContext createContext(Iterator<T> iterator) { + Variable everything = QLFactory.EVERYTHING; + IEvaluationContext context = EvaluationContext.create(parameters, everything); + context.setValue(everything, new Everything<T>(elementClass, iterator, QLUtil.needsRepeadedAccessToEverything(operand))); return context; } - public IEvaluationContext createContext(Iterator<T> iterator, Object[] params, ITranslationSupport ts) { - IEvaluationContext context = new MultiVariableContext(new ParameterContext(params), new IExpression[] {Variable.EVERYTHING, Variable.TRANSLATIONS}); - context.setValue(Variable.EVERYTHING, new Everything<T>(elementClass, iterator, operand.needsRepeatedIterations())); - context.setValue(Variable.TRANSLATIONS, ts); + public IEvaluationContext createContext(Iterator<T> iterator, ITranslationSupport ts) { + Variable everything = QLFactory.EVERYTHING; + IExpression translations = QLFactory.TRANSLATIONS; + IEvaluationContext context = EvaluationContext.create(parameters, new IExpression[] {everything, translations}); + context.setValue(everything, new Everything<T>(elementClass, iterator, QLUtil.needsRepeadedAccessToEverything(operand))); + context.setValue(translations, ts); return context; } @@ -50,26 +62,31 @@ final class ContextExpression<T> extends Unary implements IContextExpression<T> } public int getExpressionType() { - return operand.getExpressionType(); + return 0; } - String getOperator() { + public String getOperator() { throw new UnsupportedOperationException(); } - int getPriority() { + public int getPriority() { return operand.getPriority(); } - Expression pipeFrom(Expression expr) { - return new ContextExpression<T>(elementClass, operand.pipeFrom(expr)); + public Object[] getParameters() { + return parameters; } - boolean isBoolean() { - return operand.isBoolean(); + public int hashCode() { + return operand.hashCode(); } - boolean isCollection() { - return operand.isCollection(); + @SuppressWarnings("unchecked") + public Iterator<T> iterator(IEvaluationContext context) { + return (Iterator<T>) evaluateAsIterator(context); + } + + public void toString(StringBuffer bld) { + toString(bld, QLFactory.EVERYTHING); } } diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/LambdaExpression.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/CurryedLambdaExpression.java index cdc1d7216..dfdeb7b76 100644 --- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/LambdaExpression.java +++ b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/CurryedLambdaExpression.java @@ -10,31 +10,25 @@ *******************************************************************************/ package org.eclipse.equinox.internal.p2.ql.expression; -import org.eclipse.equinox.internal.p2.ql.MultiVariableContext; -import org.eclipse.equinox.internal.p2.ql.SingleVariableContext; -import org.eclipse.equinox.p2.ql.IEvaluationContext; -import org.eclipse.equinox.p2.ql.IExpressionVisitor; +import org.eclipse.equinox.internal.p2.metadata.expression.*; +import org.eclipse.equinox.p2.metadata.expression.IEvaluationContext; +import org.eclipse.equinox.p2.metadata.expression.IExpressionVisitor; +import org.eclipse.equinox.p2.ql.IQLExpression; /** * A function that executes some code */ -final class LambdaExpression extends Unary { +final class CurryedLambdaExpression extends LambdaExpression implements IQLConstants, IQLExpression { private static final Assignment[] emptyAssignmentArray = new Assignment[0]; private final Assignment[] assignments; - private final Variable each; - LambdaExpression(Variable each, Expression body, Assignment[] assignments) { - super(body); - this.each = each; + CurryedLambdaExpression(Variable each, Assignment[] assignments, Expression body) { + super(each, body); if (assignments == null) assignments = emptyAssignmentArray; this.assignments = assignments; } - LambdaExpression(Variable variable, Expression body) { - this(variable, body, null); - } - public boolean accept(IExpressionVisitor visitor) { if (super.accept(visitor) && each.accept(visitor)) { for (int idx = 0; idx < assignments.length; ++idx) @@ -45,73 +39,53 @@ final class LambdaExpression extends Unary { return false; } - public int getExpressionType() { - return TYPE_LAMBDA; + public int compareTo(Expression e) { + int cmp = super.compareTo(e); + if (cmp == 0) + cmp = compare(assignments, ((CurryedLambdaExpression) e).assignments); + return cmp; } - public void toString(StringBuffer bld) { + public boolean equals(Object o) { + return super.equals(o) && equals(assignments, ((CurryedLambdaExpression) o).assignments); + } + + public int hashCode() { + return 31 * super.hashCode() + hashCode(assignments); + } + + public void toString(StringBuffer bld, Variable rootVariable) { int top = assignments.length; if (top > 0) { for (int idx = 0; idx < top; ++idx) { - appendOperand(bld, assignments[idx].rhs, PRIORITY_COMMA); + appendOperand(bld, rootVariable, assignments[idx].rhs, IExpressionConstants.PRIORITY_COMMA); bld.append(", "); //$NON-NLS-1$ } - bld.append(OPERATOR_EACH); + bld.append(IQLConstants.OPERATOR_EACH); bld.append(", {"); //$NON-NLS-1$ for (int idx = 0; idx < top; ++idx) { - appendOperand(bld, assignments[idx].lhs, PRIORITY_COMMA); + appendOperand(bld, rootVariable, assignments[idx].lhs, IExpressionConstants.PRIORITY_COMMA); bld.append(", "); //$NON-NLS-1$ } } - each.toString(bld); - bld.append(" | "); //$NON-NLS-1$ - appendOperand(bld, operand, PRIORITY_COMMA); + super.toString(bld, rootVariable); if (top > 0) bld.append('}'); } - int countReferenceToEverything() { - if (super.countReferenceToEverything() > 0) - return 2; - for (int idx = 0; idx < assignments.length; ++idx) - if (assignments[idx].countReferenceToEverything() > 0) - return 2; - return 0; - } - - Variable getItemVariable() { - return each; - } - - String getOperator() { - return "|"; //$NON-NLS-1$ - } - - int getPriority() { - return PRIORITY_LAMBDA; - } - - boolean isBoolean() { - return operand.isBoolean(); - } - - boolean isCollection() { - return operand.isCollection(); - } - - IEvaluationContext prolog(IEvaluationContext context) { - IEvaluationContext lambdaContext = new SingleVariableContext(context, each); + public IEvaluationContext prolog(IEvaluationContext context) { + IEvaluationContext lambdaContext = super.prolog(context); int top = assignments.length; if (top > 0) { if (top == 1) { Assignment v = assignments[0]; - lambdaContext = new SingleVariableContext(lambdaContext, v.lhs); + lambdaContext = EvaluationContext.create(lambdaContext, v.lhs); lambdaContext.setValue(v.lhs, v.rhs.evaluate(context)); } else { Variable[] vars = new Variable[top]; for (int idx = 0; idx < top; ++idx) vars[idx] = (Variable) assignments[idx].lhs; - lambdaContext = new MultiVariableContext(lambdaContext, vars); + lambdaContext = EvaluationContext.create(lambdaContext, vars); for (int idx = 0; idx < top; ++idx) lambdaContext.setValue(vars[idx], assignments[idx].rhs.evaluate(context)); } diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Equals.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Equals.java deleted file mode 100644 index 773fb75b4..000000000 --- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Equals.java +++ /dev/null @@ -1,60 +0,0 @@ -/******************************************************************************* - * 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 org.eclipse.equinox.p2.ql.IEvaluationContext; - -/** - * An expression that performs the == and != comparisons - */ -final class Equals extends Binary { - final boolean negate; - - Equals(Expression lhs, Expression rhs, boolean negate) { - super(lhs, rhs); - this.negate = negate; - assertNotCollection(lhs, "lhs"); //$NON-NLS-1$ - assertNotCollection(rhs, "rhs"); //$NON-NLS-1$ - } - - public Object evaluate(IEvaluationContext context) { - Object lval = lhs.evaluate(context); - Object rval = rhs.evaluate(context); - boolean result; - if (lval == null || rval == null) - result = lval == rval; - else { - if (lval.getClass() != rval.getClass()) { - if (lval instanceof String) - rval = rval.toString(); - else if (rval instanceof String) - lval = lval.toString(); - } - result = lval.equals(rval); - } - if (negate) - result = !result; - return Boolean.valueOf(result); - } - - public int getExpressionType() { - return negate ? TYPE_NOT_EQUALS : TYPE_EQUALS; - } - - String getOperator() { - return negate ? OPERATOR_NOT_EQUALS : OPERATOR_EQUALS; - } - - boolean isBoolean() { - return true; - } - -} diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Exists.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Exists.java deleted file mode 100644 index 71e967aec..000000000 --- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Exists.java +++ /dev/null @@ -1,46 +0,0 @@ -/******************************************************************************* - * 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.Iterator; -import org.eclipse.equinox.p2.ql.IEvaluationContext; - -/** - * A collection filter that yields true if the <code>filter</code> yields true for - * any of the elements of the <code>collection</code> - */ -final class Exists extends CollectionFilter { - Exists(Expression collection, LambdaExpression lambda) { - super(collection, lambda); - } - - public int getExpressionType() { - return TYPE_EXISTS; - } - - Object evaluate(IEvaluationContext context, Iterator<?> itor) { - Variable variable = lambda.getItemVariable(); - while (itor.hasNext()) { - variable.setValue(context, itor.next()); - if (lambda.evaluate(context) == Boolean.TRUE) - return Boolean.TRUE; - } - return Boolean.FALSE; - } - - String getOperator() { - return KEYWORD_EXISTS; - } - - boolean isBoolean() { - return true; - } -} diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Expression.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Expression.java deleted file mode 100644 index fcace814a..000000000 --- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Expression.java +++ /dev/null @@ -1,174 +0,0 @@ -/******************************************************************************* - * 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.*; -import org.eclipse.equinox.internal.p2.ql.IRepeatableIterator; -import org.eclipse.equinox.internal.p2.ql.RepeatableIterator; -import org.eclipse.equinox.internal.p2.ql.parser.IParserConstants; -import org.eclipse.equinox.p2.ql.*; -import org.eclipse.equinox.p2.query.IQueryResult; - -/** - * The base class of the expression tree. - */ -abstract class Expression implements IExpression, IParserConstants { - - static final Expression[] emptyArray = new Expression[0]; - - static Set<?> asSet(Object val, boolean forcePrivateCopy) { - if (val == null) - throw new IllegalArgumentException("Cannot convert null into an set"); //$NON-NLS-1$ - - if (val instanceof IRepeatableIterator<?>) { - Object provider = ((IRepeatableIterator<?>) val).getIteratorProvider(); - if (!forcePrivateCopy) { - if (provider instanceof Set<?>) - return (Set<?>) provider; - if (provider instanceof IQueryResult<?>) - return ((IQueryResult<?>) provider).unmodifiableSet(); - } - - if (provider instanceof Collection<?>) - val = provider; - } else { - if (!forcePrivateCopy) { - if (val instanceof Set<?>) - return (Set<?>) val; - if (val instanceof IQueryResult<?>) - return ((IQueryResult<?>) val).unmodifiableSet(); - } - } - - HashSet<Object> result; - if (val instanceof Collection<?>) - result = new HashSet<Object>((Collection<?>) val); - else { - result = new HashSet<Object>(); - Iterator<?> iterator = RepeatableIterator.create(val); - while (iterator.hasNext()) - result.add(iterator.next()); - } - return result; - } - - /** - * Let the visitor visit this instance and all expressions that this - * instance contains. - * @param visitor The visiting visitor. - * @return <code>true</code> if the visitor should continue visiting, <code>false</code> otherwise. - */ - public boolean accept(IExpressionVisitor visitor) { - return visitor.accept(this); - } - - /** - * Evaluate this expression with given context and variables. - * @param context The evaluation context - * @return The result of the evaluation. - */ - public abstract Object evaluate(IEvaluationContext context); - - public Iterator<?> evaluateAsIterator(IEvaluationContext context) { - Object value = evaluate(context); - if (!(value instanceof Iterator<?>)) - value = RepeatableIterator.create(value); - return (Iterator<?>) value; - } - - /** - * Checks if the expression will make repeated requests for the 'everything' iterator. - * @return <code>true</code> if repeated requests will be made, <code>false</code> if not. - */ - public boolean needsRepeatedIterations() { - return countReferenceToEverything() > 1; - } - - public final boolean needsTranslations() { - final boolean[] translationSupportNeeded = new boolean[] {false}; - accept(new IExpressionVisitor() { - public boolean accept(IExpression expr) { - if (((Expression) expr).isReferencingTranslations()) { - translationSupportNeeded[0] = true; - return false; - } - return true; - } - }); - return translationSupportNeeded[0]; - } - - public String toString() { - StringBuffer bld = new StringBuffer(); - toString(bld); - return bld.toString(); - } - - public abstract void toString(StringBuffer bld); - - static void appendOperand(StringBuffer bld, Expression operand, int priority) { - if (priority < operand.getPriority()) { - bld.append('('); - operand.toString(bld); - bld.append(')'); - } else - operand.toString(bld); - } - - void assertNotCollection(Expression expr, String usage) { - if (expr.isCollection()) - throw new IllegalArgumentException("A collection cannot be used as " + usage + " in a " + getOperator()); //$NON-NLS-1$//$NON-NLS-2$ - } - - void assertNotBoolean(Expression expr, String usage) { - if (expr.isBoolean()) - throw new IllegalArgumentException("A boolean cannot be used as " + usage + " in a " + getOperator()); //$NON-NLS-1$//$NON-NLS-2$ - } - - int countReferenceToEverything() { - return 0; - } - - abstract String getOperator(); - - abstract int getPriority(); - - boolean isBoolean() { - return false; - } - - boolean isCollection() { - return false; - } - - boolean isElementBoolean() { - return false; - } - - boolean isReferencingTranslations() { - return false; - } - - boolean isPipeable() { - // TODO Auto-generated method stub - return false; - } - - Expression pipeFrom(Expression nxt) { - // TODO Auto-generated method stub - return null; - } - - boolean isElementCollection() { - // TODO Auto-generated method stub - return false; - } -} diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/FilterFunction.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/FilterFunction.java index 5f0130c36..0a4f96995 100644 --- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/FilterFunction.java +++ b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/FilterFunction.java @@ -10,34 +10,26 @@ *******************************************************************************/ package org.eclipse.equinox.internal.p2.ql.expression; -import org.eclipse.equinox.internal.p2.metadata.LDAPQuery; -import org.eclipse.equinox.internal.p2.ql.QLActivator; -import org.osgi.framework.InvalidSyntaxException; +import org.eclipse.equinox.internal.p2.metadata.expression.Expression; +import org.eclipse.equinox.p2.metadata.expression.ExpressionUtil; /** * A function that creates an OSGi filter based on a String */ -final class FilterFunction extends Function { +public final class FilterFunction extends Function { public FilterFunction(Expression[] operands) { super(assertLength(operands, 1, 1, KEYWORD_FILTER)); - assertNotBoolean(operands[0], "parameter"); //$NON-NLS-1$ - assertNotCollection(operands[0], "parameter"); //$NON-NLS-1$ } boolean assertSingleArgumentClass(Object v) { - return v instanceof LDAPQuery || v instanceof String; + return v instanceof String; } Object createInstance(Object arg) { - String str = (arg instanceof LDAPQuery) ? ((LDAPQuery) arg).getFilter() : (String) arg; - try { - return QLActivator.context.createFilter(str); - } catch (InvalidSyntaxException e) { - throw new IllegalArgumentException(e.getMessage()); - } + return ExpressionUtil.parseLDAP((String) arg); } - String getOperator() { + public String getOperator() { return KEYWORD_FILTER; } } diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/First.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/First.java index d587ab0bb..decd15906 100644 --- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/First.java +++ b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/First.java @@ -11,22 +11,20 @@ package org.eclipse.equinox.internal.p2.ql.expression; import java.util.Iterator; -import org.eclipse.equinox.p2.ql.IEvaluationContext; +import org.eclipse.equinox.internal.p2.metadata.expression.*; +import org.eclipse.equinox.p2.metadata.expression.IEvaluationContext; +import org.eclipse.equinox.p2.ql.IQLExpression; /** * A collection filter that yields the first element of the <code>collection</code> for which * the <code>filter</code> yields <code>true</code> */ -final class First extends CollectionFilter { +final class First extends CollectionFilter implements IQLExpression { First(Expression collection, LambdaExpression lambda) { super(collection, lambda); } - public int getExpressionType() { - return TYPE_FIRST; - } - - Object evaluate(IEvaluationContext context, Iterator<?> itor) { + protected Object evaluate(IEvaluationContext context, Iterator<?> itor) { Variable variable = lambda.getItemVariable(); while (itor.hasNext()) { Object each = itor.next(); @@ -37,15 +35,11 @@ final class First extends CollectionFilter { return null; } - String getOperator() { - return KEYWORD_FIRST; - } - - boolean isBoolean() { - return operand.isElementBoolean(); + public int getExpressionType() { + return TYPE_FIRST; } - boolean isCollection() { - return operand.isElementCollection(); + public String getOperator() { + return IQLConstants.KEYWORD_FIRST; } } diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Flatten.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Flatten.java index bb94afcb7..b0ff4122c 100644 --- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Flatten.java +++ b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Flatten.java @@ -11,8 +11,9 @@ package org.eclipse.equinox.internal.p2.ql.expression; import java.util.Iterator; +import org.eclipse.equinox.internal.p2.metadata.expression.Expression; import org.eclipse.equinox.internal.p2.ql.FlattenIterator; -import org.eclipse.equinox.p2.ql.IEvaluationContext; +import org.eclipse.equinox.p2.metadata.expression.IEvaluationContext; /** * An expression that yields a new collection consisting of all elements of the @@ -31,7 +32,7 @@ final class Flatten extends UnaryCollectionFilter { return TYPE_FLATTEN; } - String getOperator() { + public String getOperator() { return KEYWORD_FLATTEN; } } diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Function.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Function.java index 5497dca2b..d704681f2 100644 --- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Function.java +++ b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Function.java @@ -10,19 +10,34 @@ *******************************************************************************/ package org.eclipse.equinox.internal.p2.ql.expression; -import org.eclipse.equinox.p2.ql.IEvaluationContext; +import java.util.Iterator; +import org.eclipse.equinox.internal.p2.metadata.expression.*; +import org.eclipse.equinox.p2.metadata.expression.IEvaluationContext; +import org.eclipse.equinox.p2.ql.IQLExpression; /** * An expression that represents a function such as filter(<expr>) or version(<expr>) */ -abstract class Function extends NAry { +public abstract class Function extends NAry implements IQLExpression { private Object instance; - Function(Expression[] operands) { + protected Function(Expression[] operands) { super(operands); } + boolean assertSingleArgumentClass(Object v) { + return true; + } + + Object createInstance(Object arg) { + throw new UnsupportedOperationException(); + } + + final Object createInstance(String arg) { + throw new UnsupportedOperationException(); + } + public Object evaluate(IEvaluationContext context) { if (instance != null) return instance; @@ -31,7 +46,7 @@ abstract class Function extends NAry { Object arg = operand.evaluate(context); if (assertSingleArgumentClass(arg)) { Object result = createInstance(arg); - if (operand instanceof Constant || operand instanceof Parameter) + if (operand instanceof Literal || operand instanceof Parameter) // operand won't change over time so we can cache this instance. instance = result; return result; @@ -40,38 +55,25 @@ abstract class Function extends NAry { throw new IllegalArgumentException("Cannot create a " + getOperator() + " from " + what); //$NON-NLS-1$ //$NON-NLS-2$ } - boolean assertSingleArgumentClass(Object v) { - return true; + public Iterator<?> evaluateAsIterator(IEvaluationContext context) { + Object value = evaluate(context); + if (!(value instanceof Iterator<?>)) + value = RepeatableIterator.create(value); + return (Iterator<?>) value; } public int getExpressionType() { return TYPE_FUNCTION; } - public void toString(StringBuffer bld) { + public int getPriority() { + return PRIORITY_FUNCTION; + } + + public void toString(StringBuffer bld, Variable rootVariable) { bld.append(getOperator()); bld.append('('); - Array.elementsToString(bld, operands); + elementsToString(bld, rootVariable, operands); bld.append(')'); } - - final Object createInstance(String arg) { - throw new UnsupportedOperationException(); - } - - Object createInstance(Object arg) { - throw new UnsupportedOperationException(); - } - - int getPriority() { - return PRIORITY_CONSTRUCTOR; - } - - boolean isBoolean() { - return false; - } - - boolean isCollection() { - return false; - } } diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/IQLConstants.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/IQLConstants.java new file mode 100644 index 000000000..397cc13ed --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/IQLConstants.java @@ -0,0 +1,30 @@ +package org.eclipse.equinox.internal.p2.ql.expression; + +public interface IQLConstants { + String KEYWORD_CAPABILITY_INDEX = "capabilityIndex"; //$NON-NLS-1$ + String KEYWORD_COLLECT = "collect"; //$NON-NLS-1$ + String KEYWORD_FIRST = "first"; //$NON-NLS-1$ + String KEYWORD_FLATTEN = "flatten"; //$NON-NLS-1$ + String KEYWORD_INTERSECT = "intersect"; //$NON-NLS-1$ + String KEYWORD_IQUERY = "iquery"; //$NON-NLS-1$ + String KEYWORD_LATEST = "latest"; //$NON-NLS-1$ + String KEYWORD_LIMIT = "limit"; //$NON-NLS-1$ + String KEYWORD_LOCALIZED_KEYS = "localizedKeys"; //$NON-NLS-1$ + String KEYWORD_LOCALIZED_MAP = "localizedMap"; //$NON-NLS-1$ + String KEYWORD_LOCALIZED_PROPERTY = "localizedProperty"; //$NON-NLS-1$ + String KEYWORD_SATISFIES_ALL = "satisfiesAll"; //$NON-NLS-1$ + String KEYWORD_SATISFIES_ANY = "satisfiesAny"; //$NON-NLS-1$ + String KEYWORD_SELECT = "select"; //$NON-NLS-1$ + String KEYWORD_SET = "set"; //$NON-NLS-1$ + String KEYWORD_TRAVERSE = "traverse"; //$NON-NLS-1$ + String KEYWORD_UNION = "union"; //$NON-NLS-1$ + String KEYWORD_UNIQUE = "unique"; //$NON-NLS-1$ + + String VARIABLE_TRANSLATIONS = "translations"; //$NON-NLS-1$ + + String OPERATOR_ARRAY = "[]"; //$NON-NLS-1$ + String OPERATOR_ASSIGN = "="; //$NON-NLS-1$ + String OPERATOR_EACH = "_"; //$NON-NLS-1$ + String OPERATOR_ELSE = ":"; //$NON-NLS-1$ + String OPERATOR_IF = "?"; //$NON-NLS-1$ +} diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Intersect.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Intersect.java new file mode 100644 index 000000000..db6b81a5f --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Intersect.java @@ -0,0 +1,53 @@ +/******************************************************************************* + * 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.*; +import org.eclipse.equinox.internal.p2.metadata.expression.*; +import org.eclipse.equinox.p2.metadata.expression.IEvaluationContext; +import org.eclipse.equinox.p2.ql.IQLExpression; + +/** + * n-ary <code>intersect</code> operator. The result is the set of elements that were found in all operands. + */ +final class Intersect extends Binary implements IQLConstants, IQLExpression { + Intersect(Expression operand, Expression param) { + super(operand, param); + } + + public Object evaluate(IEvaluationContext context) { + return evaluateAsIterator(context); + } + + public Iterator<?> evaluateAsIterator(IEvaluationContext context) { + Set<?> resultSet = QLUtil.asSet(lhs.evaluate(context), false); // Safe since it will not be modified + Iterator<?> itor = rhs.evaluateAsIterator(context); + Set<Object> retained = new HashSet<Object>(); + while (itor.hasNext()) { + Object value = itor.next(); + if (resultSet.contains(value)) + retained.add(value); + } + return RepeatableIterator.create(retained); + } + + public int getExpressionType() { + return TYPE_INTERSECT; + } + + public String getOperator() { + return KEYWORD_INTERSECT; + } + + public int getPriority() { + return PRIORITY_COLLECTION; + } +} diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Latest.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Latest.java index c1557298a..b5c6c720e 100644 --- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Latest.java +++ b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Latest.java @@ -11,8 +11,9 @@ package org.eclipse.equinox.internal.p2.ql.expression; import java.util.*; +import org.eclipse.equinox.internal.p2.metadata.expression.*; import org.eclipse.equinox.p2.metadata.IVersionedId; -import org.eclipse.equinox.p2.ql.IEvaluationContext; +import org.eclipse.equinox.p2.metadata.expression.IEvaluationContext; /** * An expression that is especially targeted towards {@link IVersionedId} instances. It will @@ -87,7 +88,7 @@ final class Latest extends UnaryCollectionFilter { return TYPE_LATEST; } - String getOperator() { + public String getOperator() { return KEYWORD_LATEST; } } diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Limit.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Limit.java index 926a073b4..10b8051d7 100644 --- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Limit.java +++ b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Limit.java @@ -12,12 +12,14 @@ package org.eclipse.equinox.internal.p2.ql.expression; import java.util.Iterator; import java.util.NoSuchElementException; -import org.eclipse.equinox.p2.ql.IEvaluationContext; +import org.eclipse.equinox.internal.p2.metadata.expression.*; +import org.eclipse.equinox.p2.metadata.expression.IEvaluationContext; +import org.eclipse.equinox.p2.ql.IQLExpression; /** * A collection filter that limits the number of entries in the collection */ -final class Limit extends Binary { +final class Limit extends Binary implements IQLConstants, IQLExpression { /** * An iterator that stops iterating after a given number of iterations. @@ -50,15 +52,17 @@ final class Limit extends Binary { Limit(Expression operand, Expression param) { super(operand, param); - assertNotBoolean(operand, "operand"); //$NON-NLS-1$ - assertNotCollection(param, "parameter"); //$NON-NLS-1$ } Limit(Expression operand, int limit) { - this(operand, Constant.create(new Integer(limit))); + this(operand, (Expression) QLFactory.INSTANCE.constant(new Integer(limit))); } public Object evaluate(IEvaluationContext context) { + return evaluateAsIterator(context); + } + + public Iterator<?> evaluateAsIterator(IEvaluationContext context) { Object rval = rhs.evaluate(context); int limit = -1; if (rval instanceof Integer) @@ -72,25 +76,17 @@ final class Limit extends Binary { return TYPE_LIMIT; } - public void toString(StringBuffer bld) { - CollectionFilter.appendProlog(bld, lhs, getOperator()); - appendOperand(bld, rhs, PRIORITY_COMMA); + public void toString(StringBuffer bld, Variable rootVariable) { + CollectionFilter.appendProlog(bld, rootVariable, lhs, getOperator()); + appendOperand(bld, rootVariable, rhs, IExpressionConstants.PRIORITY_COMMA); bld.append(')'); } - String getOperator() { + public String getOperator() { return KEYWORD_LIMIT; } - int getPriority() { + public int getPriority() { return PRIORITY_COLLECTION; } - - boolean isCollection() { - return true; - } - - boolean isElementBoolean() { - return lhs.isElementBoolean(); - } } diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/MatchExpression.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/MatchExpression.java deleted file mode 100644 index dadd153bb..000000000 --- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/MatchExpression.java +++ /dev/null @@ -1,64 +0,0 @@ -/******************************************************************************* - * 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 org.eclipse.equinox.internal.p2.ql.*; -import org.eclipse.equinox.p2.ql.*; - -/** - * The match expression is the top expression in item queries. It introduces the - * variable 'item' and initializes it with the item to match. - */ -final class MatchExpression extends Unary implements IMatchExpression { - - MatchExpression(Expression expression) { - super(expression); - } - - public boolean isMatch(IEvaluationContext context, Object value) { - Variable.ITEM.setValue(context, value); - return operand.evaluate(context) == Boolean.TRUE; - } - - public IEvaluationContext createContext(Object[] params) { - return new SingleVariableContext(new ParameterContext(params), Variable.ITEM); - } - - public IEvaluationContext createContext(Object[] params, ITranslationSupport ts) { - IEvaluationContext context = new MultiVariableContext(new ParameterContext(params), new IExpression[] {Variable.ITEM, Variable.TRANSLATIONS}); - context.setValue(Variable.TRANSLATIONS, ts); - return context; - } - - public int getExpressionType() { - return operand.getExpressionType(); - } - - public void toString(StringBuffer bld) { - operand.toString(bld); - } - - protected int getPriority() { - return operand.getPriority(); - } - - String getOperator() { - throw new UnsupportedOperationException(); - } - - Expression pipeFrom(Expression expr) { - return new MatchExpression(operand.pipeFrom(expr)); - } - - boolean isBoolean() { - return true; - } -} diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Matches.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Matches.java index 6114347f4..eabf19fd7 100644 --- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Matches.java +++ b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Matches.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009 Cloudsmith Inc. and others. + * 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 @@ -11,9 +11,9 @@ package org.eclipse.equinox.internal.p2.ql.expression; import java.util.*; +import org.eclipse.equinox.internal.p2.metadata.expression.Expression; +import org.eclipse.equinox.internal.p2.metadata.expression.LDAPApproximation; import org.eclipse.equinox.p2.metadata.*; -import org.eclipse.equinox.p2.ql.IEvaluationContext; -import org.eclipse.equinox.p2.ql.SimplePattern; import org.osgi.framework.Filter; /** @@ -22,74 +22,18 @@ import org.osgi.framework.Filter; * <p>The following things can be matched:</p> * <table border="1" cellpadding="3"> * <tr><th>LHS</th><th>RHS</th><th>Implemented as</th></tr> - * <tr><td>IProvidedCapability</td><td>IRequiredCapability</td><td>lhs.satisfies(rhs)</td></tr> - * <tr><td>IInstallableUnit</td><td>IRequiredCapability</td><td>lhs.satisfies(rhs)</td></tr> + * <tr><td>IProvidedCapability</td><td>IRequirement</td><td>lhs.satisfies(rhs)</td></tr> + * <tr><td>IInstallableUnit</td><td>IRequirement</td><td>lhs.satisfies(rhs)</td></tr> * <tr><td>Version</td><td>VersionRange</td><td>rhs.isIncluded(lhs)</td></tr> * <tr><td>IInstallableUnit</td><td>Filter</td><td>rhs.matches(lhs.properties)</td></tr> * <tr><td>Map</td><td>Filter</td><td>rhs.match(lhs)</td></tr> - * <tr><td>String</td><td>Pattern</td><td>rhs.matcher(lhs).matches()</td></tr> - * <tr><td><any></td><td>Class</td><td>rhs.isInstance(lhs)</td></tr> - * <tr><td>Class</td><td>Class</td><td>rhs.isAssignableFrom(lhs)</td></tr> + * <tr><td>{@link String}</td><td>{@link SimplePattern}</td><td>rhs.isMatch(lhs)</td></tr> + * <tr><td>{@link String}</td><td>{@link LDAPApproximation}</td><td>rhs.isMatch(lhs)</td></tr> + * <tr><td><any></td><td>{@link Class}</td><td>rhs.isInstance(lhs)</td></tr> + * <tr><td>{@link Class}</td><td>{@link Class}</td><td>rhs.isAssignableFrom(lhs)</td></tr> * </table> */ -final class Matches extends Binary { - Matches(Expression lhs, Expression rhs) { - super(lhs, rhs); - assertNotBoolean(lhs, "lhs"); //$NON-NLS-1$ - assertNotBoolean(rhs, "rhs"); //$NON-NLS-1$ - assertNotCollection(rhs, "rhs"); //$NON-NLS-1$ - } - - public Object evaluate(IEvaluationContext context) { - Object lval = lhs.evaluate(context); - Object rval = rhs.evaluate(context); - - if (rval instanceof IRequirement) { - IRequirement requirement = (IRequirement) rval; - if (lval instanceof IInstallableUnit) - return Boolean.valueOf(((IInstallableUnit) lval).satisfies(requirement)); - if (lval instanceof IProvidedCapability) - return Boolean.valueOf(((IProvidedCapability) lval).satisfies(requirement)); - - } else if (rval instanceof VersionRange) { - if (lval instanceof Version) - return Boolean.valueOf(((VersionRange) rval).isIncluded((Version) lval)); - - } else if (rval instanceof SimplePattern) { - if (lval instanceof CharSequence) - return Boolean.valueOf(((SimplePattern) rval).isMatch((CharSequence) lval)); - - } else if (rval instanceof IUpdateDescriptor) { - if (lval instanceof IInstallableUnit) - return Boolean.valueOf(((IUpdateDescriptor) rval).isUpdateOf((IInstallableUnit) lval)); - - } else if (rval instanceof Filter) { - if (lval instanceof IInstallableUnit) - return Boolean.valueOf(((Filter) rval).match(new Hashtable<String, String>(((IInstallableUnit) lval).getProperties()))); - if (lval instanceof Dictionary<?, ?>) - return Boolean.valueOf(((Filter) rval).match((Dictionary<?, ?>) lval)); - if (lval instanceof Map<?, ?>) - return Boolean.valueOf(((Filter) rval).match(new Hashtable<Object, Object>((Map<?, ?>) lval))); - - } else if (rval instanceof Locale) { - if (lval instanceof String) - return Boolean.valueOf(matchLocaleVariants((Locale) rval, (String) lval)); - - } else if (rval instanceof Class<?>) { - Class<?> rclass = (Class<?>) rval; - return Boolean.valueOf(lval instanceof Class<?> ? rclass.isAssignableFrom((Class<?>) lval) : rclass.isInstance(lval)); - } - - if (lval == null || rval == null) - return Boolean.FALSE; - - throw new IllegalArgumentException("Cannot match a " + lval.getClass().getName() + " with a " + rval.getClass().getName()); //$NON-NLS-1$//$NON-NLS-2$ - } - - public int getExpressionType() { - return TYPE_MATCHES; - } - +final class Matches extends org.eclipse.equinox.internal.p2.metadata.expression.Matches { private static boolean equals(String a, String b, int startPos, int endPos) { if (endPos - startPos != b.length()) return false; @@ -118,11 +62,35 @@ final class Matches extends Binary { : equals(lval, rval.getCountry(), countryStart, uscore) && equals(lval, rval.getVariant(), uscore + 1, lval.length()); } - String getOperator() { - return OPERATOR_MATCHES; + Matches(Expression lhs, Expression rhs) { + super(lhs, rhs); } - boolean isBoolean() { - return true; + protected boolean match(Object lval, Object rval) { + if (rval instanceof IRequirement) { + IRequirement requirement = (IRequirement) rval; + if (lval instanceof IInstallableUnit) + return Boolean.valueOf(((IInstallableUnit) lval).satisfies(requirement)); + } else if (rval instanceof VersionRange) { + if (lval instanceof Version) + return Boolean.valueOf(((VersionRange) rval).isIncluded((Version) lval)); + + } else if (rval instanceof IUpdateDescriptor) { + if (lval instanceof IInstallableUnit) + return Boolean.valueOf(((IUpdateDescriptor) rval).isUpdateOf((IInstallableUnit) lval)); + + } else if (rval instanceof Filter) { + if (lval instanceof IInstallableUnit) + return Boolean.valueOf(((Filter) rval).match(new Hashtable<String, String>(((IInstallableUnit) lval).getProperties()))); + if (lval instanceof Dictionary<?, ?>) + return Boolean.valueOf(((Filter) rval).match((Dictionary<?, ?>) lval)); + if (lval instanceof Map<?, ?>) + return Boolean.valueOf(((Filter) rval).match(new Hashtable<Object, Object>((Map<?, ?>) lval))); + + } else if (rval instanceof Locale) { + if (lval instanceof String) + return Boolean.valueOf(matchLocaleVariants((Locale) rval, (String) lval)); + } + return super.match(lval, rval); } } diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Member.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Member.java deleted file mode 100644 index 21c99e40c..000000000 --- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Member.java +++ /dev/null @@ -1,197 +0,0 @@ -/******************************************************************************* - * 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.lang.reflect.*; -import java.util.Iterator; -import org.eclipse.equinox.p2.metadata.IRequirement; -import org.eclipse.equinox.p2.ql.*; - -/** - * <p>An expression that performs member calls to obtain some value - * from some object instance. It uses standard bean semantics so - * that an attempt to obtain "value" will cause an - * attempt to call <code>getValue()</code> and if no such method - * exists, <code>isValue()</code> and if that doesn't work either, - * <code>value()</code>.</p> - */ -abstract class Member extends Unary { - - static Member createDynamicMember(Expression operand, String name) { - return new DynamicMember(operand, name); - } - - static final Object[] NO_ARGS = new Object[0]; - - final String name; - final Expression[] argExpressions; - - static abstract class CapabilityIndexMethod extends Member { - public CapabilityIndexMethod(Expression operand, String name, Expression[] args) { - super(operand, name, args); - } - - final ICapabilityIndex getSelf(IEvaluationContext context) { - Object self = operand.evaluate(context); - if (self instanceof ICapabilityIndex) - return (ICapabilityIndex) self; - throw new IllegalArgumentException("lhs of member expected to be an ICapabilityIndex implementation"); //$NON-NLS-1$ - } - - public final Object evaluate(IEvaluationContext context) { - return evaluateAsIterator(context); - } - - boolean isCollection() { - return true; - } - } - - static final class CapabilityIndex_satisfiesAny extends CapabilityIndexMethod { - - public CapabilityIndex_satisfiesAny(Expression operand, Expression[] argExpressions) { - super(operand, KEYWORD_SATISFIES_ANY, NAry.assertLength(argExpressions, 1, 1, KEYWORD_SATISFIES_ANY)); - } - - @SuppressWarnings("unchecked") - public Iterator<?> evaluateAsIterator(IEvaluationContext context) { - return getSelf(context).satisfiesAny((Iterator<IRequirement>) argExpressions[0].evaluateAsIterator(context)); - } - } - - static final class CapabilityIndex_satisfiesAll extends CapabilityIndexMethod { - - public CapabilityIndex_satisfiesAll(Expression operand, Expression[] argExpressions) { - super(operand, KEYWORD_SATISFIES_ALL, NAry.assertLength(argExpressions, 1, 1, KEYWORD_SATISFIES_ALL)); - } - - @SuppressWarnings("unchecked") - public Iterator<?> evaluateAsIterator(IEvaluationContext context) { - return getSelf(context).satisfiesAll((Iterator<IRequirement>) argExpressions[0].evaluateAsIterator(context)); - } - } - - public boolean accept(IExpressionVisitor visitor) { - if (super.accept(visitor)) - for (int idx = 0; idx < argExpressions.length; ++idx) - if (!argExpressions[idx].accept(visitor)) - return false; - return true; - } - - Member(Expression operand, String name, Expression[] args) { - super(operand); - this.name = name; - this.argExpressions = args; - } - - public int getExpressionType() { - return TYPE_MEMBER; - } - - public void toString(StringBuffer bld) { - if (operand == Variable.ITEM || operand == Variable.EVERYTHING) - bld.append(name); - else { - appendOperand(bld, operand, getPriority()); - bld.append('.'); - bld.append(name); - } - if (argExpressions.length > 0) { - bld.append('('); - Array.elementsToString(bld, argExpressions); - bld.append(')'); - } - } - - String getOperator() { - return OPERATOR_MEMBER; - } - - int getPriority() { - return PRIORITY_MEMBER; - } - - static final class DynamicMember extends Member { - private static final Class<?>[] NO_ARG_TYPES = new Class[0]; - private static final String GET_PREFIX = "get"; //$NON-NLS-1$ - private static final String IS_PREFIX = "is"; //$NON-NLS-1$ - - DynamicMember(Expression operand, String name) { - super(operand, name, Expression.emptyArray); - if (!(name.startsWith(GET_PREFIX) || name.startsWith(IS_PREFIX))) - name = GET_PREFIX + Character.toUpperCase(name.charAt(0)) + name.substring(1); - this.methodName = name; - } - - private Class<?> lastClass; - private Method method; - private String methodName; - - public Object evaluate(IEvaluationContext context) { - return invoke(operand.evaluate(context)); - } - - boolean isReferencingTranslations() { - return VARIABLE_TRANSLATIONS.equals(name); - } - - Object invoke(Object self) { - if (self == null) - throw new IllegalArgumentException("Cannot access member " + name + " in null"); //$NON-NLS-1$//$NON-NLS-2$ - - Class<?> c = self.getClass(); - if (lastClass == null || !lastClass.isAssignableFrom(c)) { - Method m; - for (;;) { - try { - m = c.getMethod(methodName, NO_ARG_TYPES); - if (!Modifier.isPublic(m.getModifiers())) - throw new NoSuchMethodException(); - break; - } catch (NoSuchMethodException e) { - if (methodName.startsWith(GET_PREFIX)) - // Switch from using getXxx() to isXxx() - methodName = IS_PREFIX + Character.toUpperCase(name.charAt(0)) + name.substring(1); - else if (methodName.startsWith(IS_PREFIX)) - // Switch from using isXxx() to xxx() - methodName = name; - else - throw new IllegalArgumentException("Cannot find a public member " + name + " in a " + self.getClass().getName()); //$NON-NLS-1$//$NON-NLS-2$ - } - } - - // Since we already checked that it's public. This will speed - // up the calls a bit. - m.setAccessible(true); - lastClass = c; - method = m; - } - - Exception checked; - try { - return method.invoke(self, NO_ARGS); - } catch (IllegalArgumentException e) { - throw e; - } catch (IllegalAccessException e) { - checked = e; - } catch (InvocationTargetException e) { - Throwable cause = e.getTargetException(); - if (cause instanceof RuntimeException) - throw (RuntimeException) cause; - if (cause instanceof Error) - throw (Error) cause; - checked = (Exception) cause; - } - throw new RuntimeException("Problem invoking " + methodName + " on a " + self.getClass().getName(), checked); //$NON-NLS-1$ //$NON-NLS-2$ - } - } -} diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/NAry.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/NAry.java deleted file mode 100644 index 22595deb7..000000000 --- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/NAry.java +++ /dev/null @@ -1,87 +0,0 @@ -/******************************************************************************* - * 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 org.eclipse.equinox.p2.ql.IExpressionVisitor; - -/** - * The abstract baseclass for all N-ary expressions - * - */ -abstract class NAry extends Expression { - static Expression[] assertLength(Expression[] operands, int length, String operand) { - if (operands == null) - operands = emptyArray; - if (operands.length < length) - throw new IllegalArgumentException("Not enough operands for " + operand); //$NON-NLS-1$ - return operands; - } - - static Expression[] assertLength(Expression[] operands, int minLength, int maxLength, String operand) { - if (operands == null) - operands = emptyArray; - if (operands.length < minLength) - throw new IllegalArgumentException("Not enough operands for " + operand); //$NON-NLS-1$ - if (operands.length > maxLength) - throw new IllegalArgumentException("Too many operands for " + operand); //$NON-NLS-1$ - return operands; - } - - final Expression[] operands; - - NAry(Expression[] operands) { - this.operands = operands; - } - - public boolean accept(IExpressionVisitor visitor) { - if (super.accept(visitor)) - for (int idx = 0; idx < operands.length; ++idx) - if (!operands[idx].accept(visitor)) - return false; - return true; - } - - public void toString(StringBuffer bld) { - appendOperand(bld, operands[0], getPriority()); - for (int idx = 1; idx < operands.length; ++idx) { - bld.append(' '); - bld.append(getOperator()); - bld.append(' '); - appendOperand(bld, operands[idx], getPriority()); - } - } - - int countReferenceToEverything() { - int count = 0; - for (int idx = 0; count < 2 && idx < operands.length; ++idx) - count += operands[idx].countReferenceToEverything(); - return count; - } - - abstract String getOperator(); - - boolean isBoolean() { - int idx = operands.length; - while (--idx >= 0) - if (!operands[idx].isBoolean()) - return false; - return true; - } - - boolean isCollection() { - int idx = operands.length; - while (--idx >= 0) - if (!operands[idx].isCollection()) - return false; - return true; - } - -} diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Not.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Not.java deleted file mode 100644 index ab7b31f53..000000000 --- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Not.java +++ /dev/null @@ -1,42 +0,0 @@ -/******************************************************************************* - * 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 org.eclipse.equinox.p2.ql.IEvaluationContext; - -/** - * An expression that yields <code>true</code> when its operand does not. - */ -final class Not extends Unary { - Not(Expression operand) { - super(operand); - } - - public Object evaluate(IEvaluationContext context) { - return Boolean.valueOf(operand.evaluate(context) != Boolean.TRUE); - } - - public int getExpressionType() { - return TYPE_NOT; - } - - String getOperator() { - return OPERATOR_NOT; - } - - int getPriority() { - return PRIORITY_NOT; - } - - boolean isBoolean() { - return true; - } -} diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Or.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Or.java deleted file mode 100644 index 4892782be..000000000 --- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Or.java +++ /dev/null @@ -1,71 +0,0 @@ -/******************************************************************************* - * 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.Iterator; -import java.util.Set; -import org.eclipse.equinox.p2.ql.IEvaluationContext; - -/** - * n-ary OR operator. This operator evaluates its first operand and then checks - * the class of the result. If the class is {@link Boolean} then it is assumed - * that all other operands also evaluates to a boolean and the full evaluation is - * <code>false</code> if none of its operands evaluate to <code>true</code>. If the - * first result was not of class {@link Boolean}, then it is assumed that it can - * be accessed as an {@link Iterator} and that all other operands also evaluates to - * something that can be accessed an {@link Iterator}. The OR operator will then - * function as a UNION operator and the result is the unique sum of all elements that - * were found in all operands. - */ -final class Or extends NAry { - public Or(Expression[] operands) { - super(assertLength(operands, 2, OPERATOR_OR)); - } - - public Object evaluate(IEvaluationContext context) { - Object firstValue = operands[0].evaluate(context); - - // Determine operation mode - if (firstValue instanceof Boolean) { - // The first value was boolean. Assume that the rest are too - if (((Boolean) firstValue).booleanValue()) - return Boolean.TRUE; - - for (int idx = 1; idx < operands.length; ++idx) { - if (operands[idx].evaluate(context) == Boolean.TRUE) - return Boolean.TRUE; - } - return Boolean.FALSE; - } - - // Not a boolean. Assume that we can use an iterator on all values - @SuppressWarnings("unchecked") - Set<Object> resultSet = (Set<Object>) asSet(firstValue, true); - for (int idx = 1; idx < operands.length; ++idx) { - Iterator<?> itor = operands[idx].evaluateAsIterator(context); - while (itor.hasNext()) - resultSet.add(itor.next()); - } - return resultSet; - } - - public int getExpressionType() { - return TYPE_OR; - } - - String getOperator() { - return OPERATOR_OR; - } - - int getPriority() { - return PRIORITY_OR; - } -} diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Parameter.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Parameter.java deleted file mode 100644 index c6374ea2e..000000000 --- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Parameter.java +++ /dev/null @@ -1,64 +0,0 @@ -/******************************************************************************* - * 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 org.eclipse.equinox.p2.ql.IEvaluationContext; - -/** - * The abstract base class for the indexed and keyed parameters - */ -abstract class Parameter extends Expression { - public int getExpressionType() { - return TYPE_PARAMETER; - } - - int getPriority() { - return PRIORITY_PARAMETER; - } - - String getOperator() { - return OPERATOR_PARAMETER; - } - - static final class Indexed extends Parameter { - final int position; - - Indexed(int position) { - this.position = position; - } - - public Object evaluate(IEvaluationContext context) { - return context.getParameter(position); - } - - public void toString(StringBuffer bld) { - bld.append('$'); - bld.append(position); - } - } - - static final class Keyed extends Parameter { - final String key; - - public Keyed(String key) { - this.key = key; - } - - public Object evaluate(IEvaluationContext context) { - return context.getParameter(key); - } - - public void toString(StringBuffer bld) { - bld.append('$'); - bld.append(key); - } - } -} diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/ExpressionFactory.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/QLFactory.java index f603dd6e0..17bbb657a 100644 --- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/ExpressionFactory.java +++ b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/QLFactory.java @@ -3,13 +3,20 @@ package org.eclipse.equinox.internal.p2.ql.expression; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.util.*; -import org.eclipse.equinox.internal.p2.ql.parser.IParserConstants; -import org.eclipse.equinox.p2.ql.*; +import org.eclipse.equinox.internal.p2.metadata.expression.*; +import org.eclipse.equinox.p2.metadata.expression.IExpression; +import org.eclipse.equinox.p2.ql.IContextExpression; +import org.eclipse.equinox.p2.ql.IQLFactory; -public class ExpressionFactory implements IExpressionFactory, IParserConstants { - public static final IExpressionFactory INSTANCE = new ExpressionFactory(); +public class QLFactory extends ExpressionFactory implements IQLFactory, IQLConstants { + @SuppressWarnings("hiding") + public static final IQLFactory INSTANCE = new QLFactory(); - private static final Map<String, Constructor<?>> functionMap; + public static final Variable EVERYTHING = new Variable(IExpressionConstants.VARIABLE_EVERYTHING); + + public static final Variable TRANSLATIONS = new Variable(VARIABLE_TRANSLATIONS); + + protected static final Map<String, Constructor<?>> functionMap; static { Class<?>[] args = new Class[] {Expression[].class}; @@ -19,8 +26,8 @@ public class ExpressionFactory implements IExpressionFactory, IParserConstants { f.put(KEYWORD_FILTER, FilterFunction.class.getConstructor(args)); f.put(KEYWORD_VERSION, VersionFunction.class.getConstructor(args)); f.put(KEYWORD_RANGE, RangeFunction.class.getConstructor(args)); - f.put(KEYWORD_SET, SetFunction.class.getConstructor(args)); f.put(KEYWORD_CLASS, ClassFunction.class.getConstructor(args)); + f.put(KEYWORD_SET, SetFunction.class.getConstructor(args)); f.put(KEYWORD_IQUERY, WrappedIQuery.class.getConstructor(args)); f.put(KEYWORD_CAPABILITY_INDEX, CapabilityIndexFunction.class.getConstructor(args)); functionMap = Collections.unmodifiableMap(f); @@ -29,22 +36,12 @@ public class ExpressionFactory implements IExpressionFactory, IParserConstants { } } - private static Expression[] convertArray(IExpression[] operands) { - Expression[] ops = new Expression[operands.length]; - System.arraycopy(operands, 0, ops, 0, operands.length); - return ops; - } - - private ExpressionFactory() { - // Maintain singleton - } - - public IExpression all(IExpression collection, IExpression lambda) { - return new All((Expression) collection, (LambdaExpression) lambda); + public IExpression at(IExpression target, IExpression key) { + return new At((Expression) target, (Expression) key); } - public IExpression and(IExpression[] operands) { - return new And(convertArray(operands)); + public IExpression intersect(IExpression c1, IExpression c2) { + return new Intersect((Expression) c1, (Expression) c2); } public IExpression array(IExpression[] operands) { @@ -55,10 +52,6 @@ public class ExpressionFactory implements IExpressionFactory, IParserConstants { return new Assignment((Variable) variable, (Expression) expression); } - public IExpression at(IExpression target, IExpression key) { - return new At((Expression) target, (Expression) key); - } - public IExpression collect(IExpression collection, IExpression lambda) { return new Collect((Expression) collection, (LambdaExpression) lambda); } @@ -67,24 +60,8 @@ public class ExpressionFactory implements IExpressionFactory, IParserConstants { return new Condition((Expression) test, (Expression) ifTrue, (Expression) ifFalse); } - public IExpression constant(Object value) { - return Constant.create(value); - } - - public <T> IContextExpression<T> contextExpression(Class<T> elementClass, IExpression expr) { - return new ContextExpression<T>(elementClass, (Expression) expr); - } - - public IExpression dynamicMember(IExpression target, String name) { - return new Member.DynamicMember((Expression) target, name); - } - - public IExpression equals(IExpression lhs, IExpression rhs) { - return new Equals((Expression) lhs, (Expression) rhs, false); - } - - public IExpression exists(IExpression collection, IExpression lambda) { - return new Exists((Expression) collection, (LambdaExpression) lambda); + public <T> IContextExpression<T> contextExpression(Class<T> elementClass, IExpression expr, Object... parameters) { + return new ContextExpression<T>(elementClass, (Expression) expr, parameters); } public IExpression first(IExpression collection, IExpression lambda) { @@ -95,7 +72,7 @@ public class ExpressionFactory implements IExpressionFactory, IParserConstants { return new Flatten((Expression) collection); } - public IExpression function(Object function, IExpression[] args) { + public IExpression function(Object function, IExpression... args) { try { return (IExpression) ((Constructor<?>) function).newInstance(new Object[] {convertArray(args)}); } catch (IllegalArgumentException e) { @@ -116,36 +93,18 @@ public class ExpressionFactory implements IExpressionFactory, IParserConstants { return functionMap; } - public IExpression greater(IExpression lhs, IExpression rhs) { - return new Compare((Expression) lhs, (Expression) rhs, false, false); - } - - public IExpression indexedParameter(int index) { - return new Parameter.Indexed(index); - } - - public IExpression keyedParameter(String key) { - return new Parameter.Keyed(key); - } - - public IExpression lambda(IExpression variable, IExpression body) { - return new LambdaExpression((Variable) variable, (Expression) body); - } - - public IExpression lambda(IExpression variable, IExpression body, IExpression[] assignments) { + public IExpression lambda(IExpression variable, IExpression[] assignments, IExpression body) { + if (assignments.length == 0) + return super.lambda(variable, body); Assignment[] asgns = new Assignment[assignments.length]; System.arraycopy(assignments, 0, asgns, 0, assignments.length); - return new LambdaExpression((Variable) variable, (Expression) body, asgns); + return new CurryedLambdaExpression((Variable) variable, asgns, (Expression) body); } public IExpression latest(IExpression collection) { return new Latest((Expression) collection); } - public IExpression less(IExpression lhs, IExpression rhs) { - return new Compare((Expression) lhs, (Expression) rhs, true, false); - } - public IExpression limit(IExpression collection, IExpression limit) { return new Limit((Expression) collection, (Expression) limit); } @@ -154,60 +113,29 @@ public class ExpressionFactory implements IExpressionFactory, IParserConstants { return new Matches((Expression) lhs, (Expression) rhs); } - public IMatchExpression matchExpression(IExpression expr) { - return new MatchExpression((Expression) expr); - } - - public IExpression member(IExpression target, String name) { - return new Member.DynamicMember((Expression) target, name); - } - - public IExpression memberCall(IExpression target, String name, IExpression[] args) { + public IExpression memberCall(IExpression target, String name, IExpression... args) { if (args.length == 0) return member(target, name); Expression[] eargs = convertArray(args); - if (KEYWORD_SATISFIES_ANY.equals(name)) - return new Member.CapabilityIndex_satisfiesAny((Expression) target, eargs); - if (KEYWORD_SATISFIES_ALL.equals(name)) - return new Member.CapabilityIndex_satisfiesAll((Expression) target, eargs); + if (args.length > 0) { + if (KEYWORD_SATISFIES_ANY.equals(name)) + return new CapabilityIndexFunction.SatisfiesAny((Expression) target, eargs); + if (KEYWORD_SATISFIES_ALL.equals(name)) + return new CapabilityIndexFunction.SatisfiesAll((Expression) target, eargs); + } StringBuffer bld = new StringBuffer(); bld.append("Don't know how to do a member call with "); //$NON-NLS-1$ bld.append(name); bld.append('('); - Array.elementsToString(bld, eargs); + Expression.elementsToString(bld, null, eargs); bld.append(')'); throw new IllegalArgumentException(bld.toString()); } - public IExpression not(IExpression operand) { - if (operand instanceof Equals) { - Equals eq = (Equals) operand; - return new Equals(eq.lhs, eq.rhs, !eq.negate); - } - if (operand instanceof Compare) { - Compare cmp = (Compare) operand; - return new Compare(cmp.lhs, cmp.rhs, !cmp.compareLess, !cmp.equalOK); - } - if (operand instanceof Not) - return ((Not) operand).operand; - - return new Not((Expression) operand); - } - - public IExpression or(IExpression[] operands) { - return new Or(convertArray(operands)); - } - - public IExpression pipe(IExpression[] operands) { - if (operands.length == 0) - return null; - - Expression pipe = (Expression) operands[0]; - for (int idx = 1; idx < operands.length; ++idx) - pipe = ((Expression) operands[idx]).pipeFrom(pipe); - return pipe; + public IExpression union(IExpression c1, IExpression c2) { + return new Union((Expression) c1, (Expression) c2); } public IExpression select(IExpression collection, IExpression lambda) { @@ -218,11 +146,15 @@ public class ExpressionFactory implements IExpressionFactory, IParserConstants { return new Traverse((Expression) collection, (LambdaExpression) lambda); } - public IExpression unique(IExpression collection, IExpression cache) { - return new Unique((Expression) collection, (Expression) cache); + public IExpression variable(String name) { + if (name.equals(IExpressionConstants.VARIABLE_EVERYTHING)) + return EVERYTHING; + if (name.equals(VARIABLE_TRANSLATIONS)) + return TRANSLATIONS; + return super.variable(name); } - public IExpression variable(String name) { - return Variable.create(name); + 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/QLUtil.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/QLUtil.java new file mode 100644 index 000000000..6d790b25b --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/QLUtil.java @@ -0,0 +1,96 @@ +/******************************************************************************* + * 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.*; +import org.eclipse.equinox.internal.p2.metadata.expression.*; +import org.eclipse.equinox.p2.metadata.expression.*; +import org.eclipse.equinox.p2.query.IQueryResult; + +/** + * The base class of the expression tree. + */ +public abstract class QLUtil implements IExpression, IQLConstants { + + static Set<?> asSet(Object val, boolean forcePrivateCopy) { + if (val == null) + throw new IllegalArgumentException("Cannot convert null into an set"); //$NON-NLS-1$ + + if (val instanceof IRepeatableIterator<?>) { + Object provider = ((IRepeatableIterator<?>) val).getIteratorProvider(); + if (!forcePrivateCopy) { + if (provider instanceof Set<?>) + return (Set<?>) provider; + if (provider instanceof IQueryResult<?>) + return ((IQueryResult<?>) provider).unmodifiableSet(); + } + + if (provider instanceof Collection<?>) + val = provider; + } else { + if (!forcePrivateCopy) { + if (val instanceof Set<?>) + return (Set<?>) val; + if (val instanceof IQueryResult<?>) + return ((IQueryResult<?>) val).unmodifiableSet(); + } + } + + HashSet<Object> result; + if (val instanceof Collection<?>) + result = new HashSet<Object>((Collection<?>) val); + else { + result = new HashSet<Object>(); + Iterator<?> iterator = RepeatableIterator.create(val); + while (iterator.hasNext()) + result.add(iterator.next()); + } + return result; + } + + /** + * Checks if the expression will make repeated requests for the 'everything' iterator. + * @return <code>true</code> if repeated requests will be made, <code>false</code> if not. + */ + public static boolean needsTranslationSupport(IExpression expression) { + final boolean[] translationSupportNeeded = new boolean[] {false}; + ((Expression) expression).accept(new IExpressionVisitor() { + public boolean visit(IExpression expr) { + if (expr.getExpressionType() == TYPE_MEMBER && VARIABLE_TRANSLATIONS.equals(ExpressionUtil.getName(expr))) { + translationSupportNeeded[0] = true; + return false; + } + return true; + } + }); + return translationSupportNeeded[0]; + } + + /** + * Checks if the expression will make repeated requests for the 'everything' iterator. + * @return <code>true</code> if repeated requests will be made, <code>false</code> if not. + */ + static boolean needsRepeadedAccessToEverything(Expression expression) { + final boolean[] repeatedAccessNeeded = new boolean[] {false}; + expression.accept(new IExpressionVisitor() { + public boolean visit(IExpression expr) { + // FIXME Needs proper counting + if (expr == QLFactory.EVERYTHING) { + repeatedAccessNeeded[0] = true; + return false; + } + return true; + } + }); + // return repeatedAccessNeeded[0]; + return true; + } +} diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/RangeFunction.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/RangeFunction.java index df684b342..6733f73f9 100644 --- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/RangeFunction.java +++ b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/RangeFunction.java @@ -10,17 +10,16 @@ *******************************************************************************/ package org.eclipse.equinox.internal.p2.ql.expression; +import org.eclipse.equinox.internal.p2.metadata.expression.Expression; import org.eclipse.equinox.p2.metadata.VersionRange; /** * A function that creates a {@link VersionRange} from a String */ -final class RangeFunction extends Function { +public final class RangeFunction extends Function { public RangeFunction(Expression[] operands) { super(assertLength(operands, 1, 1, KEYWORD_RANGE)); - assertNotBoolean(operands[0], "parameter"); //$NON-NLS-1$ - assertNotCollection(operands[0], "parameter"); //$NON-NLS-1$ } boolean assertSingleArgumentClass(Object v) { @@ -31,7 +30,7 @@ final class RangeFunction extends Function { return new VersionRange((String) arg); } - String getOperator() { + public String getOperator() { return KEYWORD_RANGE; } } diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Select.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Select.java index f54ced61d..9ea863a0e 100644 --- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Select.java +++ b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Select.java @@ -11,27 +11,25 @@ package org.eclipse.equinox.internal.p2.ql.expression; import java.util.Iterator; +import org.eclipse.equinox.internal.p2.metadata.expression.*; import org.eclipse.equinox.internal.p2.ql.MatchIteratorFilter; -import org.eclipse.equinox.p2.ql.IEvaluationContext; +import org.eclipse.equinox.p2.metadata.expression.IEvaluationContext; +import org.eclipse.equinox.p2.ql.IQLExpression; /** * An expression that yields a new collection consisting of all elements of the * <code>collection</code> for which the <code>filter</code> yields <code>true</code>. */ -final class Select extends CollectionFilter { +final class Select extends CollectionFilter implements IQLExpression { Select(Expression collection, LambdaExpression lambda) { super(collection, lambda); } - public int getExpressionType() { - return TYPE_SELECT; - } - - Object evaluate(IEvaluationContext context, Iterator<?> itor) { + protected Object evaluate(IEvaluationContext context, Iterator<?> itor) { return evaluateAsIterator(context, itor); } - Iterator<?> evaluateAsIterator(final IEvaluationContext context, Iterator<?> itor) { + protected Iterator<?> evaluateAsIterator(final IEvaluationContext context, Iterator<?> itor) { return new MatchIteratorFilter<Object>(itor) { protected boolean isMatch(Object val) { lambda.getItemVariable().setValue(context, val); @@ -40,8 +38,12 @@ final class Select extends CollectionFilter { }; } - String getOperator() { - return KEYWORD_SELECT; + public int getExpressionType() { + return TYPE_SELECT; + } + + public String getOperator() { + return IQLConstants.KEYWORD_SELECT; } boolean isCollection() { diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/SetFunction.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/SetFunction.java index 3b0fa5248..f83275631 100644 --- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/SetFunction.java +++ b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/SetFunction.java @@ -11,9 +11,10 @@ package org.eclipse.equinox.internal.p2.ql.expression; import java.util.HashSet; -import org.eclipse.equinox.p2.ql.IEvaluationContext; +import org.eclipse.equinox.internal.p2.metadata.expression.Expression; +import org.eclipse.equinox.p2.metadata.expression.IEvaluationContext; -final class SetFunction extends Function { +public final class SetFunction extends Function implements IQLConstants { public SetFunction(Expression[] operands) { super(operands); @@ -26,7 +27,7 @@ final class SetFunction extends Function { return result; } - String getOperator() { + public String getOperator() { return KEYWORD_SET; } diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Traverse.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Traverse.java index fcb67d6b0..e8b0c0489 100644 --- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Traverse.java +++ b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Traverse.java @@ -11,9 +11,9 @@ package org.eclipse.equinox.internal.p2.ql.expression; import java.util.*; -import org.eclipse.equinox.internal.p2.ql.SingleVariableContext; -import org.eclipse.equinox.internal.p2.ql.parser.IParserConstants; -import org.eclipse.equinox.p2.ql.IEvaluationContext; +import org.eclipse.equinox.internal.p2.metadata.expression.*; +import org.eclipse.equinox.p2.metadata.expression.IEvaluationContext; +import org.eclipse.equinox.p2.ql.IQLExpression; /** * An expression that will collect items recursively based on a <code>rule</code>. @@ -22,43 +22,39 @@ import org.eclipse.equinox.p2.ql.IEvaluationContext; * in the new collection. All items are collected into a set and items that are already * in that set will not be perused again. The set becomes the result of the traversal. */ -final class Traverse extends CollectionFilter { +final class Traverse extends CollectionFilter implements IQLExpression { Traverse(Expression collection, LambdaExpression lambda) { super(collection, lambda); } - public int getExpressionType() { - return TYPE_TRAVERSE; - } - - Object evaluate(IEvaluationContext context, Iterator<?> itor) { + public Object evaluate(IEvaluationContext context, Iterator<?> itor) { return evaluateAsIterator(context, itor); } - Iterator<?> evaluateAsIterator(IEvaluationContext context, Iterator<?> iterator) { + public Iterator<?> evaluateAsIterator(IEvaluationContext context, Iterator<?> iterator) { HashSet<Object> collector = new HashSet<Object>(); while (iterator.hasNext()) traverse(collector, iterator.next(), context); return collector.iterator(); } - String getOperator() { - return IParserConstants.KEYWORD_TRAVERSE; + public int getExpressionType() { + return TYPE_TRAVERSE; + } + + public String getOperator() { + return IQLConstants.KEYWORD_TRAVERSE; } void traverse(Set<Object> collector, Object parent, IEvaluationContext context) { if (collector.add(parent)) { Variable variable = lambda.getItemVariable(); - context = new SingleVariableContext(context, variable); + context = EvaluationContext.create(context, variable); variable.setValue(context, parent); Iterator<?> subIterator = lambda.evaluateAsIterator(context); while (subIterator.hasNext()) traverse(collector, subIterator.next(), context); } } - - boolean isCollection() { - return true; - } } diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Unary.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Unary.java deleted file mode 100644 index ff4e017c6..000000000 --- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Unary.java +++ /dev/null @@ -1,48 +0,0 @@ -/******************************************************************************* - * 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 org.eclipse.equinox.p2.ql.IEvaluationContext; -import org.eclipse.equinox.p2.ql.IExpressionVisitor; - -/** - * The abstract base class for all unary expressions - */ -abstract class Unary extends Expression { - public final Expression operand; - - Unary(Expression operand) { - this.operand = operand; - } - - public boolean accept(IExpressionVisitor visitor) { - return super.accept(visitor) && operand.accept(visitor); - } - - public Object evaluate(IEvaluationContext context) { - return operand.evaluate(context); - } - - public void toString(StringBuffer bld) { - bld.append(getOperator()); - appendOperand(bld, operand, getPriority()); - } - - public Expression getOperand() { - return operand; - } - - int countReferenceToEverything() { - return operand.countReferenceToEverything(); - } - - abstract String getOperator(); -}
\ No newline at end of file diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/UnaryCollectionFilter.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/UnaryCollectionFilter.java index 85d2a5527..3de55abc8 100644 --- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/UnaryCollectionFilter.java +++ b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/UnaryCollectionFilter.java @@ -10,37 +10,35 @@ *******************************************************************************/ package org.eclipse.equinox.internal.p2.ql.expression; -import org.eclipse.equinox.p2.ql.IEvaluationContext; +import org.eclipse.equinox.internal.p2.metadata.expression.*; +import org.eclipse.equinox.p2.metadata.expression.IEvaluationContext; +import org.eclipse.equinox.p2.ql.IQLExpression; -abstract class UnaryCollectionFilter extends Unary { +abstract class UnaryCollectionFilter extends Unary implements IQLConstants, IQLExpression { UnaryCollectionFilter(Expression collection) { super(collection); } + public int hashCode() { + return 5 * operand.hashCode(); + } + public Object evaluate(IEvaluationContext context) { return evaluateAsIterator(context); } - public void toString(StringBuffer bld) { + public void toString(StringBuffer bld, Variable rootVariable) { if (operand instanceof Select) { Select select = (Select) operand; - CollectionFilter.appendProlog(bld, select.operand, getOperator()); - appendOperand(bld, select.lambda, getPriority()); + CollectionFilter.appendProlog(bld, rootVariable, select.operand, getOperator()); + appendOperand(bld, rootVariable, select.lambda, getPriority()); } else - CollectionFilter.appendProlog(bld, operand, getOperator()); + CollectionFilter.appendProlog(bld, rootVariable, operand, getOperator()); bld.append(')'); } - int getPriority() { + public int getPriority() { return PRIORITY_COLLECTION; } - - boolean isCollection() { - return true; - } - - boolean isElementBoolean() { - return operand.isElementBoolean(); - } } diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Union.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Union.java new file mode 100644 index 000000000..df8049a31 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Union.java @@ -0,0 +1,50 @@ +/******************************************************************************* + * 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.Iterator; +import java.util.Set; +import org.eclipse.equinox.internal.p2.metadata.expression.*; +import org.eclipse.equinox.p2.metadata.expression.IEvaluationContext; +import org.eclipse.equinox.p2.ql.IQLExpression; + +/** + */ +final class Union extends Binary implements IQLConstants, IQLExpression { + Union(Expression operand, Expression param) { + super(operand, param); + } + + public Object evaluate(IEvaluationContext context) { + return evaluateAsIterator(context); + } + + public Iterator<?> evaluateAsIterator(IEvaluationContext context) { + @SuppressWarnings("unchecked") + Set<Object> resultSet = (Set<Object>) QLUtil.asSet(lhs.evaluate(context), true); + Iterator<?> itor = rhs.evaluateAsIterator(context); + while (itor.hasNext()) + resultSet.add(itor.next()); + return RepeatableIterator.create(resultSet); + } + + public int getExpressionType() { + return TYPE_UNION; + } + + public String getOperator() { + return KEYWORD_UNION; + } + + public int getPriority() { + return PRIORITY_COLLECTION; + } +} diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Unique.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Unique.java index 6d55ba1ec..5d4953cea 100644 --- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Unique.java +++ b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Unique.java @@ -11,14 +11,16 @@ package org.eclipse.equinox.internal.p2.ql.expression; import java.util.*; +import org.eclipse.equinox.internal.p2.metadata.expression.*; import org.eclipse.equinox.internal.p2.ql.MatchIteratorFilter; -import org.eclipse.equinox.p2.ql.IEvaluationContext; +import org.eclipse.equinox.p2.metadata.expression.IEvaluationContext; +import org.eclipse.equinox.p2.ql.IQLExpression; /** * An expression that ensures that the elements of its collection is only returned * once throughout the whole query. */ -final class Unique extends Binary { +final class Unique extends Binary implements IQLConstants, IQLExpression { static class UniqueIterator<T> extends MatchIteratorFilter<T> { private final Set<T> uniqueSet; @@ -36,12 +38,14 @@ final class Unique extends Binary { Unique(Expression collection, Expression explicitCache) { super(collection, explicitCache); - assertNotBoolean(collection, "collection"); //$NON-NLS-1$ - assertNotBoolean(explicitCache, "cache"); //$NON-NLS-1$ } - @SuppressWarnings("unchecked") public Object evaluate(IEvaluationContext context) { + return evaluateAsIterator(context); + } + + @SuppressWarnings("unchecked") + public Iterator<?> evaluateAsIterator(IEvaluationContext context) { Object explicitCache = rhs.evaluate(context); Set<Object> uniqueSet; if (explicitCache == null) @@ -59,27 +63,18 @@ final class Unique extends Binary { return TYPE_UNIQUE; } - public void toString(StringBuffer bld) { - CollectionFilter.appendProlog(bld, lhs, getOperator()); - if (rhs != Constant.NULL_CONSTANT) - appendOperand(bld, rhs, PRIORITY_COMMA); + public void toString(StringBuffer bld, Variable rootVariable) { + CollectionFilter.appendProlog(bld, rootVariable, lhs, getOperator()); + if (rhs != Literal.NULL_CONSTANT) + appendOperand(bld, rootVariable, rhs, IExpressionConstants.PRIORITY_COMMA); bld.append(')'); } - String getOperator() { + public String getOperator() { return KEYWORD_UNIQUE; } - int getPriority() { + public int getPriority() { return PRIORITY_COLLECTION; } - - boolean isCollection() { - return true; - } - - boolean isElementBoolean() { - return lhs.isElementBoolean(); - } - } diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Variable.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Variable.java deleted file mode 100644 index bce472fd0..000000000 --- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/Variable.java +++ /dev/null @@ -1,87 +0,0 @@ -/******************************************************************************* - * 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.Iterator; -import org.eclipse.equinox.internal.p2.ql.IRepeatableIterator; -import org.eclipse.equinox.internal.p2.ql.RepeatableIterator; -import org.eclipse.equinox.p2.ql.IEvaluationContext; -import org.eclipse.equinox.p2.ql.IExpression; - -/** - * An expression representing a variable stack in the current thread. - */ -class Variable extends Expression { - - static final Variable EVERYTHING = new Variable(VARIABLE_EVERYTHING); - - static final Variable TRANSLATIONS = new Variable(VARIABLE_TRANSLATIONS); - - static final Variable ITEM = new Variable(VARIABLE_ITEM); - - private final String name; - - public static Variable create(String name) { - if (VARIABLE_ITEM.equals(name)) - return ITEM; - if (VARIABLE_EVERYTHING.equals(name)) - return EVERYTHING; - if (VARIABLE_TRANSLATIONS.equals(name)) - return TRANSLATIONS; - return new Variable(name); - } - - Variable(String name) { - this.name = name; - } - - public final Object evaluate(IEvaluationContext context) { - return context.getValue(this); - } - - public Iterator<?> evaluateAsIterator(IEvaluationContext context) { - Object value = context.getValue(this); - if (value instanceof IRepeatableIterator<?>) - return ((IRepeatableIterator<?>) value).getCopy(); - - Iterator<?> itor = RepeatableIterator.create(value); - setValue(context, itor); - return itor; - } - - public String getName() { - return name; - } - - public final void setValue(IEvaluationContext context, Object value) { - context.setValue(this, value); - } - - public void toString(StringBuffer bld) { - bld.append(name); - } - - public int getExpressionType() { - return TYPE_VARIABLE; - } - - int countReferenceToEverything() { - return IExpression.VARIABLE_EVERYTHING.equals(name) ? 1 : 0; - } - - int getPriority() { - return PRIORITY_VARIABLE; - } - - String getOperator() { - return "<variable>"; //$NON-NLS-1$ - } -} diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/VersionFunction.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/VersionFunction.java index 1e88287e0..cef9a70b9 100644 --- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/VersionFunction.java +++ b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/expression/VersionFunction.java @@ -10,17 +10,16 @@ *******************************************************************************/ package org.eclipse.equinox.internal.p2.ql.expression; +import org.eclipse.equinox.internal.p2.metadata.expression.Expression; import org.eclipse.equinox.p2.metadata.Version; /** * A function that creates a {@link Version} from a string */ -final class VersionFunction extends Function { +public final class VersionFunction extends Function { public VersionFunction(Expression[] operands) { super(assertLength(operands, 1, 1, KEYWORD_VERSION)); - assertNotBoolean(operands[0], "parameter"); //$NON-NLS-1$ - assertNotCollection(operands[0], "parameter"); //$NON-NLS-1$ } boolean assertSingleArgumentClass(Object v) { @@ -31,7 +30,7 @@ final class VersionFunction extends Function { return Version.create((String) arg); } - String getOperator() { + public String getOperator() { return KEYWORD_VERSION; } } 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 7b1d88bb9..2436976af 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 @@ -11,16 +11,16 @@ package org.eclipse.equinox.internal.p2.ql.expression; import java.util.Iterator; -import org.eclipse.equinox.p2.ql.IEvaluationContext; +import org.eclipse.equinox.internal.p2.metadata.expression.Expression; +import org.eclipse.equinox.internal.p2.metadata.expression.ExpressionFactory; +import org.eclipse.equinox.p2.metadata.expression.IEvaluationContext; import org.eclipse.equinox.p2.query.IMatchQuery; import org.eclipse.equinox.p2.query.IQuery; -final class WrappedIQuery extends Function { +public final class WrappedIQuery extends Function implements IQLConstants { public WrappedIQuery(Expression[] operands) { super(assertLength(operands, 1, 2, KEYWORD_IQUERY)); - assertNotBoolean(operands[0], "parameter"); //$NON-NLS-1$ - assertNotCollection(operands[0], "parameter"); //$NON-NLS-1$ } @SuppressWarnings("unchecked") @@ -32,7 +32,7 @@ final class WrappedIQuery extends Function { if (operands.length > 1) value = operands[1].evaluate(context); else - value = Variable.ITEM.evaluate(context); + value = ExpressionFactory.THIS.evaluate(context); return Boolean.valueOf(((IMatchQuery<Object>) query).isMatch(value)); } @@ -43,12 +43,12 @@ final class WrappedIQuery extends Function { if (operands.length > 1) iterator = operands[1].evaluateAsIterator(context); else - iterator = Variable.EVERYTHING.evaluateAsIterator(context); + iterator = QLFactory.EVERYTHING.evaluateAsIterator(context); return ((IQuery<Object>) query).perform((Iterator<Object>) iterator); } - String getOperator() { + public String getOperator() { return KEYWORD_IQUERY; } } diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/parser/ExpressionParser.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/parser/ExpressionParser.java deleted file mode 100644 index bd37c6d2e..000000000 --- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/parser/ExpressionParser.java +++ /dev/null @@ -1,847 +0,0 @@ -/******************************************************************************* - * 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.parser; - -import java.util.*; -import org.eclipse.equinox.p2.ql.*; - -public class ExpressionParser extends Stack<IExpression> implements IParserConstants, IExpressionParser { - private static final long serialVersionUID = 882034383978853143L; - - private static final int TOKEN_OR = 1; - private static final int TOKEN_AND = 2; - - private static final int TOKEN_EQUAL = 10; - private static final int TOKEN_NOT_EQUAL = 11; - private static final int TOKEN_LESS = 12; - private static final int TOKEN_LESS_EQUAL = 13; - private static final int TOKEN_GREATER = 14; - private static final int TOKEN_GREATER_EQUAL = 15; - private static final int TOKEN_MATCHES = 16; - - private static final int TOKEN_NOT = 20; - private static final int TOKEN_DOT = 21; - private static final int TOKEN_COMMA = 22; - private static final int TOKEN_PIPE = 23; - private static final int TOKEN_DOLLAR = 24; - private static final int TOKEN_IF = 25; - private static final int TOKEN_ELSE = 26; - - private static final int TOKEN_LP = 30; - private static final int TOKEN_RP = 31; - private static final int TOKEN_LB = 32; - private static final int TOKEN_RB = 33; - private static final int TOKEN_LC = 34; - private static final int TOKEN_RC = 35; - - private static final int TOKEN_IDENTIFIER = 40; - private static final int TOKEN_LITERAL = 41; - private static final int TOKEN_ANY = 42; - - private static final int TOKEN_NULL = 50; - private static final int TOKEN_TRUE = 51; - private static final int TOKEN_FALSE = 52; - - private static final int TOKEN_LATEST = 60; - private static final int TOKEN_LIMIT = 61; - private static final int TOKEN_FIRST = 62; - private static final int TOKEN_FLATTEN = 63; - private static final int TOKEN_UNIQUE = 64; - private static final int TOKEN_SELECT = 65; - private static final int TOKEN_COLLECT = 66; - private static final int TOKEN_TRAVERSE = 67; - private static final int TOKEN_EXISTS = 68; - private static final int TOKEN_ALL = 69; - - private static final int TOKEN_END = 0; - private static final int TOKEN_ERROR = -1; - - private static final Map<String, Integer> keywords; - static { - keywords = new HashMap<String, Integer>(); - keywords.put(KEYWORD_ALL, new Integer(TOKEN_ALL)); - keywords.put(KEYWORD_COLLECT, new Integer(TOKEN_COLLECT)); - keywords.put(KEYWORD_EXISTS, new Integer(TOKEN_EXISTS)); - keywords.put(KEYWORD_FALSE, new Integer(TOKEN_FALSE)); - keywords.put(KEYWORD_FIRST, new Integer(TOKEN_FIRST)); - keywords.put(KEYWORD_FLATTEN, new Integer(TOKEN_FLATTEN)); - keywords.put(KEYWORD_LATEST, new Integer(TOKEN_LATEST)); - keywords.put(KEYWORD_LIMIT, new Integer(TOKEN_LIMIT)); - keywords.put(KEYWORD_NULL, new Integer(TOKEN_NULL)); - keywords.put(KEYWORD_SELECT, new Integer(TOKEN_SELECT)); - keywords.put(KEYWORD_TRAVERSE, new Integer(TOKEN_TRAVERSE)); - keywords.put(KEYWORD_TRUE, new Integer(TOKEN_TRUE)); - keywords.put(KEYWORD_UNIQUE, new Integer(TOKEN_UNIQUE)); - keywords.put(OPERATOR_EACH, new Integer(TOKEN_ANY)); - } - - private final IExpressionFactory factory; - - private String expression; - private int tokenPos; - private int currentToken; - private int lastTokenPos; - private Object tokenValue; - private String rootVariable; - - public ExpressionParser(IExpressionFactory factory) { - this.factory = factory; - } - - public synchronized IMatchExpression parsePredicate(String exprString) { - expression = exprString; - tokenPos = 0; - currentToken = 0; - tokenValue = null; - rootVariable = IExpression.VARIABLE_ITEM; - IExpression itemVariable = factory.variable(IExpression.VARIABLE_ITEM); - push(itemVariable); - try { - nextToken(); - IExpression expr = currentToken == TOKEN_END ? factory.constant(Boolean.TRUE) : parseCondition(); - assertToken(TOKEN_END); - return factory.matchExpression(expr); - } finally { - popVariable(); // pop item - } - } - - public synchronized <T> IContextExpression<T> parseQuery(Class<T> elementClass, String exprString) { - expression = exprString; - tokenPos = 0; - currentToken = 0; - tokenValue = null; - rootVariable = IExpression.VARIABLE_EVERYTHING; - IExpression everythingVariable = factory.variable(IExpression.VARIABLE_EVERYTHING); - push(everythingVariable); - try { - nextToken(); - IExpression expr = parseCondition(); - assertToken(TOKEN_END); - return factory.contextExpression(elementClass, expr); - } finally { - popVariable(); // pop context - } - } - - private IExpression parseCondition() { - IExpression expr = parseOr(); - if (currentToken == TOKEN_IF) { - nextToken(); - IExpression ifTrue = parseOr(); - assertToken(TOKEN_ELSE); - nextToken(); - expr = factory.condition(expr, ifTrue, parseOr()); - } - return expr; - } - - private IExpression parseOr() { - IExpression expr = parseAnd(); - if (currentToken != TOKEN_OR) - return expr; - - ArrayList<IExpression> exprs = new ArrayList<IExpression>(); - exprs.add(expr); - do { - nextToken(); - exprs.add(parseAnd()); - } while (currentToken == TOKEN_OR); - return factory.or(exprs.toArray(new IExpression[exprs.size()])); - } - - private IExpression parseAnd() { - IExpression expr = parseBinary(); - if (currentToken != TOKEN_AND) - return expr; - - ArrayList<IExpression> exprs = new ArrayList<IExpression>(); - exprs.add(expr); - do { - nextToken(); - exprs.add(parseBinary()); - } while (currentToken == TOKEN_AND); - return factory.and(exprs.toArray(new IExpression[exprs.size()])); - } - - private IExpression parseBinary() { - IExpression expr = parseNot(); - switch (currentToken) { - case TOKEN_OR : - case TOKEN_AND : - case TOKEN_RP : - case TOKEN_RB : - case TOKEN_RC : - case TOKEN_COMMA : - case TOKEN_IF : - case TOKEN_ELSE : - case TOKEN_END : - break; - case TOKEN_EQUAL : - case TOKEN_NOT_EQUAL : - case TOKEN_GREATER : - case TOKEN_GREATER_EQUAL : - case TOKEN_LESS : - case TOKEN_LESS_EQUAL : - case TOKEN_MATCHES : - int realToken = currentToken; - nextToken(); - IExpression rhs = parseNot(); - switch (realToken) { - case TOKEN_EQUAL : - expr = factory.equals(expr, rhs); - break; - case TOKEN_NOT_EQUAL : - expr = factory.not(factory.equals(expr, rhs)); - break; - case TOKEN_GREATER : - expr = factory.greater(expr, rhs); - break; - case TOKEN_GREATER_EQUAL : - expr = factory.not(factory.less(expr, rhs)); - break; - case TOKEN_LESS : - expr = factory.less(expr, rhs); - break; - case TOKEN_LESS_EQUAL : - expr = factory.not(factory.greater(expr, rhs)); - break; - default : - expr = factory.matches(expr, rhs); - } - break; - default : - throw syntaxError(); - } - return expr; - } - - private IExpression parseNot() { - if (currentToken == TOKEN_NOT) { - nextToken(); - IExpression expr = parseNot(); - return factory.not(expr); - } - return parseCollectionExpression(); - } - - private IExpression parseCollectionExpression() { - IExpression expr; - switch (currentToken) { - case TOKEN_SELECT : - case TOKEN_COLLECT : - case TOKEN_EXISTS : - case TOKEN_FIRST : - case TOKEN_FLATTEN : - case TOKEN_ALL : - case TOKEN_TRAVERSE : - case TOKEN_LATEST : - case TOKEN_LIMIT : - case TOKEN_UNIQUE : - expr = getVariableOrRootMember(rootVariable); - break; - default : - expr = parseMember(); - if (currentToken != TOKEN_DOT) - return expr; - nextToken(); - } - - for (;;) { - int filterToken = currentToken; - nextToken(); - assertToken(TOKEN_LP); - nextToken(); - switch (filterToken) { - case TOKEN_SELECT : - expr = factory.select(expr, parseLambdaDefinition()); - break; - case TOKEN_COLLECT : - expr = factory.collect(expr, parseLambdaDefinition()); - break; - case TOKEN_EXISTS : - expr = factory.exists(expr, parseLambdaDefinition()); - break; - case TOKEN_FIRST : - expr = factory.first(expr, parseLambdaDefinition()); - break; - case TOKEN_ALL : - expr = factory.all(expr, parseLambdaDefinition()); - break; - case TOKEN_TRAVERSE : - expr = factory.traverse(expr, parseLambdaDefinition()); - break; - case TOKEN_LATEST : - if (currentToken == TOKEN_RP) { - expr = factory.latest(expr); - assertToken(TOKEN_RP); - nextToken(); - } else - expr = factory.latest(factory.select(expr, parseLambdaDefinition())); - break; - case TOKEN_FLATTEN : - if (currentToken == TOKEN_RP) { - expr = factory.flatten(expr); - assertToken(TOKEN_RP); - nextToken(); - } else - expr = factory.flatten(factory.select(expr, parseLambdaDefinition())); - break; - case TOKEN_LIMIT : - expr = factory.limit(expr, parseCondition()); - assertToken(TOKEN_RP); - nextToken(); - break; - case TOKEN_UNIQUE : - if (currentToken == TOKEN_RP) - expr = factory.unique(expr, factory.constant(null)); - else { - expr = factory.unique(expr, parseMember()); - assertToken(TOKEN_RP); - nextToken(); - } - break; - default : - throw syntaxError(); - } - if (currentToken != TOKEN_DOT) - break; - nextToken(); - } - return expr; - } - - private IExpression parseMember() { - IExpression expr = parseConstructor(); - String name; - while (currentToken == TOKEN_DOT || currentToken == TOKEN_LB) { - int savePos = tokenPos; - int saveToken = currentToken; - Object saveTokenValue = tokenValue; - nextToken(); - if (saveToken == TOKEN_DOT) { - switch (currentToken) { - case TOKEN_SELECT : - case TOKEN_COLLECT : - case TOKEN_EXISTS : - case TOKEN_FIRST : - case TOKEN_FLATTEN : - case TOKEN_ALL : - case TOKEN_TRAVERSE : - case TOKEN_LATEST : - case TOKEN_LIMIT : - case TOKEN_UNIQUE : - tokenPos = savePos; - currentToken = saveToken; - tokenValue = saveTokenValue; - return expr; - - case TOKEN_IDENTIFIER : - name = (String) tokenValue; - nextToken(); - if (currentToken == TOKEN_LP) { - nextToken(); - IExpression[] callArgs = parseArray(); - assertToken(TOKEN_RP); - nextToken(); - expr = factory.memberCall(expr, name, callArgs); - } else - expr = factory.memberCall(expr, name, IExpressionFactory.NO_ARGS); - break; - - default : - throw syntaxError(); - } - } else { - IExpression atExpr = parseMember(); - assertToken(TOKEN_RB); - nextToken(); - expr = factory.at(expr, atExpr); - } - } - return expr; - } - - private IExpression parseLambdaDefinition() { - boolean endingRC = false; - int anyIndex = -1; - IExpression[] initializers = IExpressionFactory.NO_ARGS; - IExpression[] variables; - if (currentToken == TOKEN_LC) { - // Lambda starts without currying. - endingRC = true; - nextToken(); - anyIndex = 0; - variables = parseVariables(); - if (variables == null) - // empty means no pipe at the end. - throw syntaxError(); - } else { - anyIndex = 0; - variables = parseVariables(); - if (variables == null) { - anyIndex = -1; - initializers = parseArray(); - assertToken(TOKEN_LC); - nextToken(); - endingRC = true; - for (int idx = 0; idx < initializers.length; ++idx) { - IExpression initializer = initializers[idx]; - if (initializer.getExpressionType() == IExpression.TYPE_VARIABLE && OPERATOR_EACH.equals(initializer.toString())) { - if (anyIndex == -1) - anyIndex = idx; - else - anyIndex = -1; // Second Each. This is illegal - break; - } - } - if (anyIndex == -1) - throw new IllegalArgumentException("Exaclty one _ must be present among the currying expressions"); //$NON-NLS-1$ - - variables = parseVariables(); - if (variables == null) - // empty means no pipe at the end. - throw syntaxError(); - } - - } - nextToken(); - IExpression body = parseCondition(); - if (endingRC) { - assertToken(TOKEN_RC); - nextToken(); - } - - assertToken(TOKEN_RP); - nextToken(); - IExpression each; - IExpression[] assignments; - if (initializers.length == 0) { - if (variables.length != 1) - throw new IllegalArgumentException("Must have exactly one variable unless currying is used"); //$NON-NLS-1$ - each = variables[0]; - assignments = IExpressionFactory.NO_ARGS; - } else { - if (initializers.length != variables.length) - throw new IllegalArgumentException("Number of currying expressions and variables differ"); //$NON-NLS-1$ - - if (initializers.length == 1) { - // This is just a map from _ to some variable - each = variables[0]; - assignments = IExpressionFactory.NO_ARGS; - } else { - int idx; - each = variables[anyIndex]; - assignments = new IExpression[initializers.length - 1]; - for (idx = 0; idx < anyIndex; ++idx) - assignments[idx] = factory.assignment(variables[idx], initializers[idx]); - for (++idx; idx < initializers.length; ++idx) - assignments[idx] = factory.assignment(variables[idx], initializers[idx]); - } - } - return factory.lambda(each, body, assignments); - } - - private IExpression[] parseVariables() { - int savePos = tokenPos; - int saveToken = currentToken; - Object saveTokenValue = tokenValue; - List<Object> ids = null; - while (currentToken == TOKEN_IDENTIFIER) { - if (ids == null) - ids = new ArrayList<Object>(); - ids.add(tokenValue); - nextToken(); - if (currentToken == TOKEN_COMMA) { - nextToken(); - continue; - } - break; - } - - if (currentToken != TOKEN_PIPE) { - // This was not a variable list - tokenPos = savePos; - currentToken = saveToken; - tokenValue = saveTokenValue; - return null; - } - - if (ids == null) - // Empty list but otherwise OK - return IExpressionFactory.NO_ARGS; - - int top = ids.size(); - IExpression[] result = new IExpression[top]; - for (int idx = 0; idx < top; ++idx) { - String name = (String) ids.get(idx); - IExpression var = factory.variable(name); - push(var); - result[idx] = var; - } - return result; - } - - private IExpression parseConstructor() { - if (currentToken == TOKEN_IDENTIFIER) { - int savePos = tokenPos; - int saveToken = currentToken; - Object saveTokenValue = tokenValue; - - Object function = factory.getFunctionMap().get(tokenValue); - if (function != null) { - nextToken(); - if (currentToken == TOKEN_LP) { - nextToken(); - IExpression[] args = currentToken == TOKEN_RP ? IExpressionFactory.NO_ARGS : parseArray(); - assertToken(TOKEN_RP); - nextToken(); - return factory.function(function, args); - } - tokenPos = savePos; - currentToken = saveToken; - tokenValue = saveTokenValue; - } - } - return parseUnary(); - } - - private IExpression parseUnary() { - IExpression expr; - switch (currentToken) { - case TOKEN_LP : - nextToken(); - expr = parseCondition(); - assertToken(TOKEN_RP); - nextToken(); - break; - case TOKEN_LB : - nextToken(); - expr = factory.array(parseArray()); - assertToken(TOKEN_RB); - nextToken(); - break; - case TOKEN_LITERAL : - expr = factory.constant(tokenValue); - nextToken(); - break; - case TOKEN_DOLLAR : - expr = parseParameter(); - break; - case TOKEN_IDENTIFIER : - expr = getVariableOrRootMember((String) tokenValue); - nextToken(); - break; - case TOKEN_ANY : - expr = factory.variable(OPERATOR_EACH); - nextToken(); - break; - case TOKEN_NULL : - expr = factory.constant(null); - nextToken(); - break; - case TOKEN_TRUE : - expr = factory.constant(Boolean.TRUE); - nextToken(); - break; - case TOKEN_FALSE : - expr = factory.constant(Boolean.FALSE); - nextToken(); - break; - default : - throw syntaxError(); - } - return expr; - } - - private IExpression parseParameter() { - if (currentToken == TOKEN_DOLLAR) { - nextToken(); - - IExpression param = null; - if (currentToken == TOKEN_LITERAL && tokenValue instanceof Integer) - param = factory.indexedParameter(((Integer) tokenValue).intValue()); - else if (currentToken == TOKEN_IDENTIFIER) - param = factory.keyedParameter((String) tokenValue); - - if (param != null) { - nextToken(); - return param; - } - } - throw syntaxError(); - } - - private IExpression[] parseArray() { - IExpression expr = parseCondition(); - if (currentToken != TOKEN_COMMA) - return new IExpression[] {expr}; - - ArrayList<IExpression> operands = new ArrayList<IExpression>(); - operands.add(expr); - do { - nextToken(); - if (currentToken == TOKEN_LC) - // We don't allow lambdas in the array - break; - operands.add(parseCondition()); - } while (currentToken == TOKEN_COMMA); - return operands.toArray(new IExpression[operands.size()]); - } - - private void assertToken(int token) { - if (currentToken != token) - throw syntaxError(); - } - - private IExpression getVariableOrRootMember(String id) { - int idx = size(); - while (--idx >= 0) { - IExpression v = get(idx); - if (id.equals(v.toString())) - return v; - } - - if (rootVariable.equals(id)) - throw syntaxError("No such variable: " + id); //$NON-NLS-1$ - - return factory.memberCall(getVariableOrRootMember(rootVariable), id, IExpressionFactory.NO_ARGS); - } - - private void nextToken() { - tokenValue = null; - int top = expression.length(); - char c = 0; - while (tokenPos < top) { - c = expression.charAt(tokenPos); - if (!Character.isWhitespace(c)) - break; - ++tokenPos; - } - if (tokenPos >= top) { - lastTokenPos = top; - currentToken = TOKEN_END; - return; - } - - lastTokenPos = tokenPos; - switch (c) { - case '|' : - if (tokenPos + 1 < top && expression.charAt(tokenPos + 1) == '|') { - tokenValue = OPERATOR_OR; - currentToken = TOKEN_OR; - tokenPos += 2; - } else { - currentToken = TOKEN_PIPE; - ++tokenPos; - } - break; - - case '&' : - if (tokenPos + 1 < top && expression.charAt(tokenPos + 1) == '&') { - tokenValue = OPERATOR_ARRAY; - currentToken = TOKEN_AND; - tokenPos += 2; - } else - currentToken = TOKEN_ERROR; - break; - - case '=' : - if (tokenPos + 1 < top && expression.charAt(tokenPos + 1) == '=') { - tokenValue = OPERATOR_EQUALS; - currentToken = TOKEN_EQUAL; - tokenPos += 2; - } else - currentToken = TOKEN_ERROR; - break; - - case '!' : - if (tokenPos + 1 < top && expression.charAt(tokenPos + 1) == '=') { - tokenValue = OPERATOR_NOT_EQUALS; - currentToken = TOKEN_NOT_EQUAL; - tokenPos += 2; - } else { - currentToken = TOKEN_NOT; - ++tokenPos; - } - break; - - case '~' : - if (tokenPos + 1 < top && expression.charAt(tokenPos + 1) == '=') { - tokenValue = IParserConstants.OPERATOR_MATCHES; - currentToken = TOKEN_MATCHES; - tokenPos += 2; - } else - currentToken = TOKEN_ERROR; - break; - - case '>' : - if (tokenPos + 1 < top && expression.charAt(tokenPos + 1) == '=') { - tokenValue = OPERATOR_GT_EQUAL; - currentToken = TOKEN_GREATER_EQUAL; - tokenPos += 2; - } else { - currentToken = TOKEN_GREATER; - ++tokenPos; - } - break; - - case '<' : - if (tokenPos + 1 < top && expression.charAt(tokenPos + 1) == '=') { - tokenValue = OPERATOR_LT_EQUAL; - currentToken = TOKEN_LESS_EQUAL; - tokenPos += 2; - } else { - currentToken = TOKEN_LESS; - ++tokenPos; - } - break; - - case '?' : - currentToken = TOKEN_IF; - ++tokenPos; - break; - - case ':' : - currentToken = TOKEN_ELSE; - ++tokenPos; - break; - - case '.' : - currentToken = TOKEN_DOT; - ++tokenPos; - break; - - case '$' : - currentToken = TOKEN_DOLLAR; - ++tokenPos; - break; - - case '{' : - currentToken = TOKEN_LC; - ++tokenPos; - break; - - case '}' : - currentToken = TOKEN_RC; - ++tokenPos; - break; - - case '(' : - currentToken = TOKEN_LP; - ++tokenPos; - break; - - case ')' : - currentToken = TOKEN_RP; - ++tokenPos; - break; - - case '[' : - currentToken = TOKEN_LB; - ++tokenPos; - break; - - case ']' : - currentToken = TOKEN_RB; - ++tokenPos; - break; - - case ',' : - currentToken = TOKEN_COMMA; - ++tokenPos; - break; - - case '"' : - case '\'' : { - int start = ++tokenPos; - while (tokenPos < top && expression.charAt(tokenPos) != c) - ++tokenPos; - if (tokenPos == top) { - tokenPos = start - 1; - currentToken = TOKEN_ERROR; - } else { - tokenValue = expression.substring(start, tokenPos++); - currentToken = TOKEN_LITERAL; - } - break; - } - - case '/' : { - int start = ++tokenPos; - StringBuffer buf = new StringBuffer(); - while (tokenPos < top) { - c = expression.charAt(tokenPos); - if (c == '\\' && tokenPos + 1 < top) { - c = expression.charAt(++tokenPos); - if (c != '/') - buf.append('\\'); - } else if (c == '/') - break; - buf.append(c); - ++tokenPos; - } - if (tokenPos == top) { - tokenPos = start - 1; - currentToken = TOKEN_ERROR; - } else { - tokenValue = SimplePattern.compile(expression.substring(start, tokenPos++)); - currentToken = TOKEN_LITERAL; - } - break; - } - - default : - if (Character.isDigit(c)) { - int start = tokenPos++; - while (tokenPos < top && Character.isDigit(expression.charAt(tokenPos))) - ++tokenPos; - tokenValue = Integer.valueOf(expression.substring(start, tokenPos)); - currentToken = TOKEN_LITERAL; - break; - } - if (Character.isJavaIdentifierStart(c)) { - int start = tokenPos++; - while (tokenPos < top && Character.isJavaIdentifierPart(expression.charAt(tokenPos))) - ++tokenPos; - String word = expression.substring(start, tokenPos); - Integer token = keywords.get(word); - if (token == null) - currentToken = TOKEN_IDENTIFIER; - else - currentToken = token.intValue(); - tokenValue = word; - break; - } - throw syntaxError(); - } - } - - private void popVariable() { - if (isEmpty()) - throw syntaxError(); - pop(); - } - - private QLParseException syntaxError() { - Object tv = tokenValue; - if (tv == null) { - if (lastTokenPos >= expression.length()) - return syntaxError("Unexpeced end of expression"); //$NON-NLS-1$ - tv = expression.substring(lastTokenPos, lastTokenPos + 1); - } - return syntaxError("Unexpected token \"" + tv + '"'); //$NON-NLS-1$ - } - - private QLParseException syntaxError(String message) { - return new QLParseException(expression, message, tokenPos); - } -} diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/parser/IParserConstants.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/parser/IParserConstants.java deleted file mode 100644 index 381ad712b..000000000 --- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/parser/IParserConstants.java +++ /dev/null @@ -1,75 +0,0 @@ -/******************************************************************************* - * 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.parser; - -public interface IParserConstants { - - String KEYWORD_ALL = "all"; //$NON-NLS-1$ - String KEYWORD_BOOLEAN = "boolean"; //$NON-NLS-1$ - String KEYWORD_CAPABILITY_INDEX = "capabilityIndex"; //$NON-NLS-1$ - String KEYWORD_CLASS = "class"; //$NON-NLS-1$ - String KEYWORD_COLLECT = "collect"; //$NON-NLS-1$ - String KEYWORD_EXISTS = "exists"; //$NON-NLS-1$ - String KEYWORD_FALSE = "false"; //$NON-NLS-1$ - String KEYWORD_FILTER = "filter"; //$NON-NLS-1$ - String KEYWORD_FIRST = "first"; //$NON-NLS-1$ - String KEYWORD_FLATTEN = "flatten"; //$NON-NLS-1$ - String KEYWORD_IQUERY = "iquery"; //$NON-NLS-1$ - String KEYWORD_LATEST = "latest"; //$NON-NLS-1$ - String KEYWORD_LIMIT = "limit"; //$NON-NLS-1$ - String KEYWORD_LOCALIZED_KEYS = "localizedKeys"; //$NON-NLS-1$ - String KEYWORD_LOCALIZED_MAP = "localizedMap"; //$NON-NLS-1$ - String KEYWORD_LOCALIZED_PROPERTY = "localizedProperty"; //$NON-NLS-1$ - String KEYWORD_NULL = "null"; //$NON-NLS-1$ - String KEYWORD_RANGE = "range"; //$NON-NLS-1$ - String KEYWORD_SATISFIES_ALL = "satisfiesAll"; //$NON-NLS-1$ - String KEYWORD_SATISFIES_ANY = "satisfiesAny"; //$NON-NLS-1$ - String KEYWORD_SELECT = "select"; //$NON-NLS-1$ - String KEYWORD_SET = "set"; //$NON-NLS-1$ - String KEYWORD_TRAVERSE = "traverse"; //$NON-NLS-1$ - String KEYWORD_TRUE = "true"; //$NON-NLS-1$ - String KEYWORD_UNIQUE = "unique"; //$NON-NLS-1$ - String KEYWORD_VERSION = "version"; //$NON-NLS-1$ - - String OPERATOR_AND = "&&"; //$NON-NLS-1$ - String OPERATOR_ARRAY = "[]"; //$NON-NLS-1$ - String OPERATOR_ASSIGN = "="; //$NON-NLS-1$ - String OPERATOR_AT = "[]"; //$NON-NLS-1$ - String OPERATOR_EACH = "_"; //$NON-NLS-1$ - String OPERATOR_ELSE = ":"; //$NON-NLS-1$ - String OPERATOR_EQUALS = "=="; //$NON-NLS-1$ - String OPERATOR_GT = ">"; //$NON-NLS-1$ - String OPERATOR_GT_EQUAL = ">="; //$NON-NLS-1$ - String OPERATOR_IF = "?"; //$NON-NLS-1$ - String OPERATOR_LT = "<"; //$NON-NLS-1$ - String OPERATOR_LT_EQUAL = "<="; //$NON-NLS-1$ - String OPERATOR_MATCHES = "~="; //$NON-NLS-1$ - String OPERATOR_MEMBER = "."; //$NON-NLS-1$ - String OPERATOR_NOT = "!"; //$NON-NLS-1$ - String OPERATOR_NOT_EQUALS = "!="; //$NON-NLS-1$ - String OPERATOR_OR = "||"; //$NON-NLS-1$ - String OPERATOR_PARAMETER = "$"; //$NON-NLS-1$ - - int PRIORITY_PARAMETER = 1; - int PRIORITY_VARIABLE = 1; - int PRIORITY_LITERAL = 1; - int PRIORITY_CONSTRUCTOR = 2; - int PRIORITY_MEMBER = 3; - int PRIORITY_COLLECTION = 4; - int PRIORITY_NOT = 5; - int PRIORITY_BINARY = 6; - int PRIORITY_AND = 7; - int PRIORITY_OR = 8; - int PRIORITY_CONDITION = 9; - int PRIORITY_ASSIGNMENT = 10; - int PRIORITY_LAMBDA = 11; - int PRIORITY_COMMA = 12; -} diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/parser/QLParser.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/parser/QLParser.java new file mode 100644 index 000000000..9a281dfd8 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/internal/p2/ql/parser/QLParser.java @@ -0,0 +1,384 @@ +/******************************************************************************* + * 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.parser; + +import java.util.*; +import org.eclipse.equinox.internal.p2.metadata.expression.IExpressionConstants; +import org.eclipse.equinox.internal.p2.metadata.expression.Variable; +import org.eclipse.equinox.internal.p2.metadata.expression.parser.ExpressionParser; +import org.eclipse.equinox.internal.p2.ql.expression.IQLConstants; +import org.eclipse.equinox.p2.metadata.expression.IExpression; +import org.eclipse.equinox.p2.metadata.expression.IExpressionFactory; +import org.eclipse.equinox.p2.ql.IQLFactory; +import org.eclipse.equinox.p2.ql.IQLParser; + +public class QLParser extends ExpressionParser implements IQLParser, IQLConstants { + private static final long serialVersionUID = 882034383978853143L; + + private static final int TOKEN_ANY = 42; + + private static final int TOKEN_LATEST = 70; + private static final int TOKEN_LIMIT = 71; + private static final int TOKEN_FIRST = 72; + private static final int TOKEN_FLATTEN = 73; + private static final int TOKEN_UNIQUE = 74; + private static final int TOKEN_SELECT = 75; + private static final int TOKEN_COLLECT = 76; + private static final int TOKEN_TRAVERSE = 77; + private static final int TOKEN_INTERSECT = 78; + private static final int TOKEN_UNION = 79; + + private static final Map<String, Integer> qlKeywords; + static { + qlKeywords = new HashMap<String, Integer>(); + qlKeywords.putAll(keywords); + qlKeywords.put(KEYWORD_COLLECT, new Integer(TOKEN_COLLECT)); + qlKeywords.put(KEYWORD_FALSE, new Integer(TOKEN_FALSE)); + qlKeywords.put(KEYWORD_FIRST, new Integer(TOKEN_FIRST)); + qlKeywords.put(KEYWORD_FLATTEN, new Integer(TOKEN_FLATTEN)); + qlKeywords.put(KEYWORD_LATEST, new Integer(TOKEN_LATEST)); + qlKeywords.put(KEYWORD_LIMIT, new Integer(TOKEN_LIMIT)); + qlKeywords.put(KEYWORD_NULL, new Integer(TOKEN_NULL)); + qlKeywords.put(KEYWORD_SELECT, new Integer(TOKEN_SELECT)); + qlKeywords.put(KEYWORD_TRAVERSE, new Integer(TOKEN_TRAVERSE)); + qlKeywords.put(KEYWORD_TRUE, new Integer(TOKEN_TRUE)); + qlKeywords.put(KEYWORD_UNIQUE, new Integer(TOKEN_UNIQUE)); + qlKeywords.put(KEYWORD_INTERSECT, new Integer(TOKEN_INTERSECT)); + qlKeywords.put(KEYWORD_UNION, new Integer(TOKEN_UNION)); + qlKeywords.put(OPERATOR_EACH, new Integer(TOKEN_ANY)); + } + + public QLParser(IQLFactory factory) { + super(factory); + } + + public synchronized IExpression parseQuery(String exprString) { + expression = exprString; + tokenPos = 0; + currentToken = 0; + tokenValue = null; + rootVariable = IExpressionConstants.VARIABLE_EVERYTHING; + IExpression everythingVariable = factory.variable(IExpressionConstants.VARIABLE_EVERYTHING); + push(everythingVariable); + try { + nextToken(); + IExpression expr = parseCondition(); + assertToken(TOKEN_END); + return expr; + } finally { + popVariable(); // pop context + } + } + + protected Map<String, Integer> keywordToTokenMap() { + return qlKeywords; + } + + protected IExpression parseCondition() { + IExpression expr = parseOr(); + if (currentToken == TOKEN_IF) { + nextToken(); + IExpression ifTrue = parseOr(); + assertToken(TOKEN_ELSE); + nextToken(); + expr = qlFactory().condition(expr, ifTrue, parseOr()); + } + return expr; + } + + protected IExpression parseMember() { + IExpression expr = parseFunction(); + String name; + while (currentToken == TOKEN_DOT || currentToken == TOKEN_LB) { + int savePos = tokenPos; + int saveToken = currentToken; + Object saveTokenValue = tokenValue; + nextToken(); + if (saveToken == TOKEN_DOT) { + switch (currentToken) { + case TOKEN_IDENTIFIER : + name = (String) tokenValue; + nextToken(); + if (currentToken == TOKEN_LP) { + nextToken(); + IExpression[] callArgs = parseArray(); + assertToken(TOKEN_RP); + nextToken(); + expr = qlFactory().memberCall(expr, name, callArgs); + } else + expr = factory.member(expr, name); + break; + + default : + tokenPos = savePos; + currentToken = saveToken; + tokenValue = saveTokenValue; + return expr; + } + } else { + IExpression atExpr = parseMember(); + assertToken(TOKEN_RB); + nextToken(); + expr = factory.at(expr, atExpr); + } + } + return expr; + } + + protected IExpression parseFunction() { + if (currentToken == TOKEN_IDENTIFIER) { + Object function = qlFactory().getFunctionMap().get(tokenValue); + if (function != null) { + int savePos = tokenPos; + int saveToken = currentToken; + Object saveTokenValue = tokenValue; + + nextToken(); + if (currentToken == TOKEN_LP) { + nextToken(); + IExpression[] args = currentToken == TOKEN_RP ? IExpressionFactory.NO_ARGS : parseArray(); + assertToken(TOKEN_RP); + nextToken(); + return qlFactory().function(function, args); + } + tokenPos = savePos; + currentToken = saveToken; + tokenValue = saveTokenValue; + } + } + return parseUnary(); + } + + protected IQLFactory qlFactory() { + return (IQLFactory) factory; + } + + protected IExpression parseCollectionLHS() { + IExpression expr; + switch (currentToken) { + case TOKEN_SELECT : + case TOKEN_COLLECT : + case TOKEN_FIRST : + case TOKEN_FLATTEN : + case TOKEN_TRAVERSE : + case TOKEN_LATEST : + case TOKEN_LIMIT : + case TOKEN_INTERSECT : + case TOKEN_UNION : + case TOKEN_UNIQUE : + expr = getVariableOrRootMember(rootVariable); + break; + default : + expr = super.parseCollectionLHS(); + } + return expr; + } + + protected IExpression parseCollectionRHS(IExpression expr, int funcToken) { + switch (funcToken) { + case TOKEN_SELECT : + expr = qlFactory().select(expr, parseLambdaDefinition()); + break; + case TOKEN_COLLECT : + expr = qlFactory().collect(expr, parseLambdaDefinition()); + break; + case TOKEN_FIRST : + expr = qlFactory().first(expr, parseLambdaDefinition()); + break; + case TOKEN_TRAVERSE : + expr = qlFactory().traverse(expr, parseLambdaDefinition()); + break; + case TOKEN_LATEST : + if (currentToken == TOKEN_RP) { + expr = qlFactory().latest(expr); + assertToken(TOKEN_RP); + nextToken(); + } else + expr = qlFactory().latest(qlFactory().select(expr, parseLambdaDefinition())); + break; + case TOKEN_FLATTEN : + if (currentToken == TOKEN_RP) { + expr = qlFactory().flatten(expr); + assertToken(TOKEN_RP); + nextToken(); + } else + expr = qlFactory().flatten(qlFactory().select(expr, parseLambdaDefinition())); + break; + case TOKEN_LIMIT : + expr = qlFactory().limit(expr, parseCondition()); + assertToken(TOKEN_RP); + nextToken(); + break; + case TOKEN_INTERSECT : + expr = qlFactory().intersect(expr, parseCondition()); + assertToken(TOKEN_RP); + nextToken(); + break; + case TOKEN_UNION : + expr = qlFactory().union(expr, parseCondition()); + assertToken(TOKEN_RP); + nextToken(); + break; + case TOKEN_UNIQUE : + if (currentToken == TOKEN_RP) + expr = qlFactory().unique(expr, factory.constant(null)); + else { + expr = qlFactory().unique(expr, parseMember()); + assertToken(TOKEN_RP); + nextToken(); + } + break; + default : + expr = super.parseCollectionRHS(expr, funcToken); + } + return expr; + } + + protected IExpression parseUnary() { + IExpression expr; + switch (currentToken) { + case TOKEN_LB : + nextToken(); + expr = qlFactory().array(parseArray()); + assertToken(TOKEN_RB); + nextToken(); + break; + case TOKEN_ANY : + expr = factory.variable(IQLConstants.OPERATOR_EACH); + nextToken(); + break; + default : + expr = super.parseUnary(); + } + return expr; + } + + protected IExpression parseLambdaDefinition() { + boolean endingRC = false; + int anyIndex = -1; + IExpression[] initializers = IExpressionFactory.NO_ARGS; + IExpression[] variables; + if (currentToken == TOKEN_LC) { + // Lambda starts without currying. + endingRC = true; + nextToken(); + anyIndex = 0; + variables = parseVariables(); + if (variables == null) + // empty means no pipe at the end. + throw syntaxError(); + } else { + anyIndex = 0; + variables = parseVariables(); + if (variables == null) { + anyIndex = -1; + initializers = parseArray(); + assertToken(TOKEN_LC); + nextToken(); + endingRC = true; + for (int idx = 0; idx < initializers.length; ++idx) { + IExpression initializer = initializers[idx]; + if (initializer instanceof Variable && IQLConstants.OPERATOR_EACH.equals(initializer.toString())) { + if (anyIndex == -1) + anyIndex = idx; + else + anyIndex = -1; // Second Each. This is illegal + break; + } + } + if (anyIndex == -1) + throw new IllegalArgumentException("Exaclty one _ must be present among the currying expressions"); //$NON-NLS-1$ + + variables = parseVariables(); + if (variables == null) + // empty means no pipe at the end. + throw syntaxError(); + } + + } + nextToken(); + IExpression body = parseCondition(); + if (endingRC) { + assertToken(TOKEN_RC); + nextToken(); + } + + assertToken(TOKEN_RP); + nextToken(); + IExpression each; + IExpression[] assignments; + IQLFactory qlFactory = qlFactory(); + if (initializers.length == 0) { + if (variables.length != 1) + throw new IllegalArgumentException("Must have exactly one variable unless currying is used"); //$NON-NLS-1$ + each = variables[0]; + assignments = IExpressionFactory.NO_ARGS; + } else { + if (initializers.length != variables.length) + throw new IllegalArgumentException("Number of currying expressions and variables differ"); //$NON-NLS-1$ + + if (initializers.length == 1) { + // This is just a map from _ to some variable + each = variables[0]; + assignments = IExpressionFactory.NO_ARGS; + } else { + int idx; + each = variables[anyIndex]; + assignments = new IExpression[initializers.length - 1]; + for (idx = 0; idx < anyIndex; ++idx) + assignments[idx] = qlFactory.assignment(variables[idx], initializers[idx]); + for (++idx; idx < initializers.length; ++idx) + assignments[idx] = qlFactory.assignment(variables[idx], initializers[idx]); + } + } + return qlFactory.lambda(each, assignments, body); + } + + private IExpression[] parseVariables() { + int savePos = tokenPos; + int saveToken = currentToken; + Object saveTokenValue = tokenValue; + List<Object> ids = null; + while (currentToken == TOKEN_IDENTIFIER) { + if (ids == null) + ids = new ArrayList<Object>(); + ids.add(tokenValue); + nextToken(); + if (currentToken == TOKEN_COMMA) { + nextToken(); + continue; + } + break; + } + + if (currentToken != TOKEN_PIPE) { + // This was not a variable list + tokenPos = savePos; + currentToken = saveToken; + tokenValue = saveTokenValue; + return null; + } + + if (ids == null) + // Empty list but otherwise OK + return IExpressionFactory.NO_ARGS; + + int top = ids.size(); + IExpression[] result = new IExpression[top]; + for (int idx = 0; idx < top; ++idx) { + String name = (String) ids.get(idx); + IExpression var = factory.variable(name); + push(var); + result[idx] = var; + } + return result; + } +} 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 index 0b894cc92..fa0468f0f 100644 --- 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 @@ -11,6 +11,8 @@ package org.eclipse.equinox.p2.ql; import java.util.Iterator; +import org.eclipse.equinox.p2.metadata.expression.IEvaluationContext; +import org.eclipse.equinox.p2.metadata.expression.IExpression; /** * This is an expression that will need access to the global variable @@ -18,22 +20,15 @@ import java.util.Iterator; */ public interface IContextExpression<T> extends IExpression { /** - * Returns the element class - * @return The element class - */ - Class<T> getElementClass(); - - /** * <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 params The parameters to use for the evaluation. * @return A new evaluation context. */ - IEvaluationContext createContext(Iterator<T> everything, Object[] params); + IEvaluationContext createContext(Iterator<T> everything); /** * <p>Creates a new context to be passed to a subsequent evaluation. The context @@ -42,9 +37,27 @@ public interface IContextExpression<T> extends IExpression { * <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 params The parameters to use for the evaluation. * @param translations A translation support object to be assigned to the variable 'translations' * @return A new evaluation context. */ - IEvaluationContext createContext(Iterator<T> everything, Object[] params, ITranslationSupport translations); + IEvaluationContext createContext(Iterator<T> everything, ITranslationSupport translations); + + /** + * Returns the element class + * @return The element class + */ + Class<T> getElementClass(); + + /** + * Returns the parameters that this context expression was created with. + * @return An array of parameters, possibly empty but never <code>null</code>. + */ + Object[] getParameters(); + + /** + * Evaluate the expression and return the expected collection result as an iterator + * @param context The evaluation context + * @return The result of the evaluation. + */ + Iterator<T> iterator(IEvaluationContext context); } diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/p2/ql/IEvaluationContext.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/p2/ql/IEvaluationContext.java deleted file mode 100644 index efde9f3f4..000000000 --- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/p2/ql/IEvaluationContext.java +++ /dev/null @@ -1,47 +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; - -/** - * The evaluation context. Contexts can be nested and new contexts are pushed for each closure - * during an evaluation of an expression. - * @see IMatchExpression#createContext(Object[]) - * @see IContextExpression#createContext(java.util.Iterator, Object[]) - */ -public interface IEvaluationContext { - /** - * Retrieve the value of the given <code>variable</code> from this context - * @param variable The variable who's value should be retrieved - * @return The current value for the variable - */ - Object getValue(IExpression variable); - - /** - * Set the current value for the given <code>variable</code> to <code>value</code> - * @param variable The variable who's value should be set - * @param value The new value for the variable. - */ - void setValue(IExpression variable, Object value); - - /** - * Returns the value of the parameter at the given <code>position</code> - * @param position The zero based position for the parameter - * @return The parameter value - */ - Object getParameter(int position); - - /** - * Returns the value of the parameter at the given <code>key</code> - * @param key The key for the parameter - * @return The parameter value - */ - Object getParameter(String key); -} diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/p2/ql/IExpression.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/p2/ql/IExpression.java deleted file mode 100644 index 9f959f106..000000000 --- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/p2/ql/IExpression.java +++ /dev/null @@ -1,95 +0,0 @@ -/******************************************************************************* - * 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.p2.ql; - -import java.util.Iterator; - -/** - * A node in the expression tree - */ -public interface IExpression { - int TYPE_VARIABLE = 1; - int TYPE_PARAMETER = 2; - int TYPE_LITERAL = 3; - int TYPE_AND = 4; - int TYPE_OR = 5; - int TYPE_FUNCTION = 6; - int TYPE_ARRAY = 7; - int TYPE_AT = 8; - int TYPE_MEMBER = 9; - int TYPE_ALL = 10; - int TYPE_EXISTS = 11; - int TYPE_SELECT = 12; - int TYPE_COLLECT = 13; - int TYPE_TRAVERSE = 14; - int TYPE_LATEST = 15; - int TYPE_FLATTEN = 16; - int TYPE_LIMIT = 17; - int TYPE_FIRST = 18; - int TYPE_LAMBDA = 19; - int TYPE_EQUALS = 20; - int TYPE_GREATER = 21; - int TYPE_LESS = 22; - int TYPE_GREATER_EQUAL = 23; - int TYPE_LESS_EQUAL = 24; - int TYPE_MATCHES = 25; - int TYPE_NOT = 26; - int TYPE_ASSIGNMENT = 27; - int TYPE_CONDITION = 28; - int TYPE_NOT_EQUALS = 29; - int TYPE_UNIQUE = 30; - - String VARIABLE_TRANSLATIONS = "translations"; //$NON-NLS-1$ - String VARIABLE_EVERYTHING = "everything"; //$NON-NLS-1$ - String VARIABLE_ITEM = "item"; //$NON-NLS-1$ - - /** - * Let the visitor visit this instance and all expressions that this - * instance contains. - * @param visitor The visiting visitor. - * @return <code>true</code> if the visitor should continue visiting, <code>false</code> otherwise. - */ - boolean accept(IExpressionVisitor visitor); - - /** - * Evaluate this expression with given context and variables. - * @param context The evaluation context - * @return The result of the evaluation. - */ - Object evaluate(IEvaluationContext context); - - /** - * Evaluate this expression with given context and variables and return a result - * in the form of an iterator. - * @param context The evaluation context - * @return The result of the evaluation. - */ - Iterator<?> evaluateAsIterator(IEvaluationContext context); - - /** - * Returns the expression type (see TYPE_xxx constants). - */ - int getExpressionType(); - - /** - * Checks if this expression will need an instance of {@link ITranslationSupport} to execute - * @return <code>true</code> if translation support is needed. - */ - boolean needsTranslations(); - - /** - * A special toString method that can be used when efficient string concatenation is - * desired. Avoids the need to create new StringBuffer instances for each concatenation - * when traversing the expression tree. - * @param receiver The receiver of the string representation. - */ - void toString(StringBuffer receiver); -} diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/p2/ql/IExpressionVisitor.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/p2/ql/IExpressionVisitor.java deleted file mode 100644 index 14a7fa038..000000000 --- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/p2/ql/IExpressionVisitor.java +++ /dev/null @@ -1,25 +0,0 @@ -/******************************************************************************* - * 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.p2.ql; - -/** - * A general purpose visitor that will visit each node in an expression tree. - */ -public interface IExpressionVisitor { - /** - * The method that will be called for each expression that is - * visited. - * @param expression The expression that the visitor visits. - * @return <code>true</code> to continue visiting other expressions or - * <code>false</code> to break out. - */ - boolean accept(IExpression expression); -}
\ No newline at end of file diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/p2/ql/IMatchExpression.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/p2/ql/IMatchExpression.java deleted file mode 100644 index cd9dff4dd..000000000 --- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/p2/ql/IMatchExpression.java +++ /dev/null @@ -1,43 +0,0 @@ -/******************************************************************************* - * 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.p2.ql; - -/** - * The item expression is the top expression in item queries. It introduces the - * variable 'item' and initializes it with the item to match. - */ -public interface IMatchExpression extends IExpression { - /** - * <p>Creates a new context to be passed to a subsequent evaluation. The context - * will introduce 'item' as an uninitialized variable and make the parameters available. - * @param params The parameters to use for the evaluation. - * @return A new evaluation context. - */ - IEvaluationContext createContext(Object[] params); - - /** - * <p>Creates a new context to be passed to a subsequent evaluation. The context - * will introduce 'item' as an uninitialized variable and make the parameters available. - * @param params The parameters to use for the evaluation. - * @param translations A translation support object to be assigned to the variable 'translations' - * @return A new evaluation context. - */ - IEvaluationContext createContext(Object[] params, ITranslationSupport translations); - - /** - * This method assigns <code>candidate</code> to the 'item' variable of the - * <code>context</code> and then evaluates the expression. - * @param context A context previously created with {@link #createContext(Object[])} - * @param candidate The object to test. - * @return the result of the evaluation. - */ - boolean isMatch(IEvaluationContext context, Object candidate); -} 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 new file mode 100644 index 000000000..905bb85b5 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/p2/ql/IQLExpression.java @@ -0,0 +1,20 @@ +package org.eclipse.equinox.p2.ql; + +import org.eclipse.equinox.p2.metadata.expression.IExpression; + +public interface IQLExpression extends IExpression { + int TYPE_ARRAY = 20; + int TYPE_ASSIGNMENT = 21; + int TYPE_COLLECT = 22; + int TYPE_CONDITION = 23; + int TYPE_FIRST = 24; + int TYPE_FLATTEN = 25; + int TYPE_FUNCTION = 26; + 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; +} diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/p2/ql/IExpressionFactory.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/p2/ql/IQLFactory.java index 3ca1ca331..501dff83f 100644 --- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/p2/ql/IExpressionFactory.java +++ b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/p2/ql/IQLFactory.java @@ -12,30 +12,14 @@ package org.eclipse.equinox.p2.ql; 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; /** * This inteface provides all the factory methods needed to create the all possible * nodes of the expression tree. */ -public interface IExpressionFactory { - IExpression[] NO_ARGS = new IExpression[0]; - - /** - * Create a collection filter that yields true if the <code>lambda</code> yields true for - * all of the elements of the <code>collection</code> - * @param collection The collection providing the elements to test - * @param lambda The lambda that performs the test - * @return A boolean expression - */ - IExpression all(IExpression collection, IExpression lambda); - - /** - * Create a logical <i>and</i> of its <code>operands</code>. - * @param operands The boolean operands - * @return A boolean expression - */ - IExpression and(IExpression[] operands); - +public interface IQLFactory extends IExpressionFactory { /** * Create an array of elements. * @param elements The elements of the array @@ -52,15 +36,6 @@ public interface IExpressionFactory { IExpression assignment(IExpression variable, IExpression expression); /** - * Create an lookup of <code>key</code> in the <code>target</code>. - * The key expression should evaluate to a string or an integer. - * @param target The target for the lookup - * @param key The key to use for the lookup - * @return A lookup expression - */ - IExpression at(IExpression target, IExpression key); - - /** * Create an expression that collects the result of evaluating each element in a new collection. * @param collection The collection providing the elements to evaluate * @param lambda The lambda that creates each new element @@ -80,35 +55,13 @@ public interface IExpressionFactory { IExpression condition(IExpression test, IExpression ifTrue, IExpression ifFalse); /** - * Creates an expression that evaluates to the constant <code>value</code>. - * @param value The constant - * @return A constant expression - */ - IExpression constant(Object value); - - /** * Creates a top level expression that represents a full query. + * @param elementClass The element class of the queried material * @param expr The query + * @param parameters The parameters of the query * @return A top level query expression */ - <T> IContextExpression<T> contextExpression(Class<T> elementClass, IExpression expr); - - /** - * Create an expression that tests if <code>lhs</code> is equal to <code>rhs</code>. - * @param lhs The left hand side value. - * @param rhs The right hand side value. - * @return A boolean expression - */ - IExpression equals(IExpression lhs, IExpression rhs); - - /** - * Create a collection filter that yields true if the <code>lambda</code> yields true for - * at least one of the elements of the <code>collection</code> - * @param collection The collection providing the elements to test - * @param lambda The lambda that performs the test - * @return A boolean expression - */ - IExpression exists(IExpression collection, IExpression lambda); + <T> IContextExpression<T> contextExpression(Class<T> elementClass, IExpression expr, Object... parameters); /** * Create an expression that yields the first element of the @@ -128,13 +81,13 @@ public interface IExpressionFactory { IExpression flatten(IExpression collection); /** - * Given one of the value in the {@link Map} returned by {@link #getFunctionMap()}, this method + * Given one of the values in the map returned by {@link #getFunctionMap()}, this method * returns a function expression. * @param function The value obtained from the map. * @param args The arguments to evaluate and pass when evaluating the function. * @return A function expression */ - IExpression function(Object function, IExpression[] args); + IExpression function(Object function, IExpression... args); /** * Returns a map of functions supported by this factory. The map is keyed by @@ -145,45 +98,22 @@ public interface IExpressionFactory { Map<String, ? extends Object> getFunctionMap(); /** - * Create an expression that tests if <code>lhs</code> is greater than <code>rhs</code>. - * @param lhs The left hand side value. - * @param rhs The right hand side value. - * @return A boolean expression - */ - IExpression greater(IExpression lhs, IExpression rhs); - - /** - * Creates an indexed parameter expression - * @param index The index to use - * @return a parameter expression - */ - IExpression indexedParameter(int index); - - /** - * Creates an keyed parameter expression - * @param key The key to use - * @return a parameter expression + * 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 keyedParameter(String key); - - /** - * Creates a lambda expression that takes exactly one variable. Suitable for use - * in most collection expressions. - * @param body The body of the lambda - * @param variable The element variable that the lambda uses - * @return A lambda expression - */ - IExpression lambda(IExpression body, IExpression variable); + 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 body The body of the lambda * @param variable The element variable that the lambda uses + * @param body The body of the lambda * @param initialAssignments Assignments to evaluate once before calling the body for each element. * @return A lambda expression with currying */ - IExpression lambda(IExpression body, IExpression variable, IExpression[] initialAssignments); + IExpression lambda(IExpression variable, IExpression[] initialAssignments, IExpression body); /** * Create an expression that yields a new collection consisting of the latest version of @@ -195,14 +125,6 @@ public interface IExpressionFactory { IExpression latest(IExpression collection); /** - * Create an expression that tests if <code>lhs</code> is less than <code>rhs</code>. - * @param lhs The left hand side value. - * @param rhs The right hand side value. - * @return A boolean expression - */ - IExpression less(IExpression lhs, IExpression rhs); - - /** * Create an expression that yields a new collection consisting of the <i>n</i> first * elements of the source collection where <i>n</i> is determined by <code>limit</code>. * @param collection The source collection @@ -211,50 +133,13 @@ public interface IExpressionFactory { IExpression limit(IExpression collection, IExpression limit); /** - * Create an expression that tests if <code>lhs</code> matches <code>rhs</code>. - * @param lhs The left hand side value. - * @param rhs The right hand side value. - * @return A boolean expression - */ - IExpression matches(IExpression lhs, IExpression rhs); - - /** - * Creates a top level expression suitable for predicate matching - * @param expr The boolean expression - * @return A top level predicate expression - */ - IMatchExpression matchExpression(IExpression expr); - - /** - * Creates a member accessor expression. - * @param target The target for the member access - * @param name The name of the member - * @return A member expression - */ - IExpression member(IExpression target, String name); - - /** * Creates a member call expression. * @param target The target for the member call * @param name The name of the member * @param args The arguments to use for the call * @return A member expression */ - IExpression memberCall(IExpression target, String name, IExpression[] args); - - /** - * Creates an expression that negates the result of evaluating its <code>operand</code>. - * @param operand The boolean expression to negate - * @return A boolean expression - */ - IExpression not(IExpression operand); - - /** - * Create a logical <i>or</i> of its <code>operands</code>. - * @param operands The boolean operands - * @return A boolean expression - */ - IExpression or(IExpression[] operands); + IExpression memberCall(IExpression target, String name, IExpression... args); /** * Create an expression that yields a new collection consisting of all elements of the @@ -283,6 +168,14 @@ public interface 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. @@ -291,11 +184,4 @@ public interface IExpressionFactory { * @return A collection expression */ IExpression unique(IExpression collection, IExpression cache); - - /** - * Creates an expression that represents a variable - * @param name The name of the variable - * @return A variable expression - */ - IExpression variable(String name); } diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/p2/ql/IExpressionParser.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/p2/ql/IQLParser.java index 5dbaf6f57..8b327a3de 100644 --- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/p2/ql/IExpressionParser.java +++ b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/p2/ql/IQLParser.java @@ -10,20 +10,14 @@ *******************************************************************************/ package org.eclipse.equinox.p2.ql; +import org.eclipse.equinox.p2.metadata.expression.IExpression; +import org.eclipse.equinox.p2.metadata.expression.IExpressionParser; + /** * A parser that produces an expression tree based on a string representation. An - * implementation will use the {@link IExpressionFactory} to create the actual expressions + * implementation will use the {@link IQLFactory} to create the actual expressions */ -public interface IExpressionParser { - /** - * Create a new boolean expression. The expression will have access to the global - * variable 'item' and to the context parameters. - * @param exprString The string representing the boolean expression. - * @return The resulting expression tree. - * @throws QLParseException - */ - IMatchExpression parsePredicate(String exprString); - +public interface IQLParser extends IExpressionParser { /** * Create an arbitrary expression. The expression will have access to the global * variable 'everything' and to the context parameters. @@ -31,5 +25,5 @@ public interface IExpressionParser { * @return The resulting expression tree. * @throws QLParseException */ - <T> IContextExpression<T> parseQuery(Class<T> elementClass, String exprString); + IExpression parseQuery(String exprString); } diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/p2/ql/QL.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/p2/ql/QL.java index 32633cdcd..7d34a8b9c 100644 --- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/p2/ql/QL.java +++ b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/p2/ql/QL.java @@ -12,8 +12,8 @@ package org.eclipse.equinox.p2.ql; import java.util.Iterator; import org.eclipse.equinox.internal.p2.ql.QueryContext; -import org.eclipse.equinox.internal.p2.ql.expression.ExpressionFactory; -import org.eclipse.equinox.internal.p2.ql.parser.ExpressionParser; +import org.eclipse.equinox.internal.p2.ql.expression.QLFactory; +import org.eclipse.equinox.internal.p2.ql.parser.QLParser; import org.eclipse.equinox.p2.query.IQueryable; /** @@ -24,16 +24,16 @@ public abstract class QL { * Returns the default expression factory. * @return the default expression factory. */ - public static IExpressionFactory getFactory() { - return ExpressionFactory.INSTANCE; + public static IQLFactory getFactory() { + return QLFactory.INSTANCE; } /** * Creates a new instance of the default expression parser. * @return the new parser. */ - public static IExpressionParser newParser() { - return new ExpressionParser(getFactory()); + public static IQLParser newParser() { + return new QLParser(getFactory()); } /** 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 3798627fb..83e63bbbd 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 @@ -11,6 +11,8 @@ 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.IEvaluationContext; import org.eclipse.equinox.p2.query.IQueryResult; /** @@ -21,11 +23,10 @@ public class QLContextQuery<T> extends QLQuery<T> { /** * Creates a new query instance with indexed parameters. - * @param expression The expression that represents the query. * @param parameters Parameters to use for the query. */ - public QLContextQuery(IContextExpression<T> expression, Object... parameters) { - super(expression.getElementClass(), parameters); + public QLContextQuery(IContextExpression<T> expression) { + super(expression.getElementClass()); this.expression = expression; } @@ -36,7 +37,7 @@ public class QLContextQuery<T> extends QLQuery<T> { * @param parameters Parameters to use for the query. */ public QLContextQuery(Class<T> elementClass, String expression, Object... parameters) { - this(parser.parseQuery(elementClass, expression), parameters); + this(QL.getFactory().contextExpression(elementClass, parser.parseQuery(expression), parameters)); } public IQueryResult<T> perform(Iterator<T> iterator) { @@ -45,13 +46,12 @@ public class QLContextQuery<T> extends QLQuery<T> { public Iterator<T> evaluate(Iterator<T> iterator) { IEvaluationContext ctx; - if (expression.needsTranslations()) { + if (QLUtil.needsTranslationSupport(expression)) { IQueryContext<T> queryContext = QL.newQueryContext(iterator); - ctx = expression.createContext(iterator, parameters, queryContext.getTranslationSupport(getLocale())); + ctx = expression.createContext(iterator, queryContext.getTranslationSupport(getLocale())); } else - ctx = expression.createContext(iterator, parameters); - @SuppressWarnings("unchecked") - Iterator<T> result = (Iterator<T>) expression.evaluateAsIterator(ctx); + ctx = expression.createContext(iterator); + Iterator<T> result = expression.iterator(ctx); return result; } @@ -64,10 +64,10 @@ public class QLContextQuery<T> extends QLQuery<T> { // Check if we need translation support // IEvaluationContext ctx; - if (expression.needsTranslations()) - ctx = expression.createContext(queryContext.iterator(), parameters, queryContext.getTranslationSupport(getLocale())); + if (QLUtil.needsTranslationSupport(expression)) + ctx = expression.createContext(queryContext.iterator(), queryContext.getTranslationSupport(getLocale())); else - ctx = expression.createContext(queryContext.iterator(), parameters); + ctx = expression.createContext(queryContext.iterator()); return expression.evaluate(ctx); } } 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 index 118398a23..b06750470 100644 --- 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 @@ -12,6 +12,10 @@ 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; @@ -19,7 +23,7 @@ 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 expression; + private final IMatchExpression<T> expression; private IEvaluationContext context; /** @@ -28,8 +32,8 @@ public class QLMatchQuery<T> extends QLQuery<T> implements IMatchQuery<T> { * @param expression The expression that represents the query. * @param parameters Parameters to use for the query. */ - public QLMatchQuery(Class<T> instanceClass, IMatchExpression expression, Object... parameters) { - super(instanceClass, parameters); + public QLMatchQuery(Class<T> instanceClass, IMatchExpression<T> expression) { + super(instanceClass); this.expression = expression; } @@ -40,7 +44,7 @@ public class QLMatchQuery<T> extends QLQuery<T> implements IMatchQuery<T> { * @param parameters Parameters to use for the query. */ public QLMatchQuery(Class<T> instanceClass, String expression, Object... parameters) { - this(instanceClass, parser.parsePredicate(expression), parameters); + this(instanceClass, QL.getFactory().<T> matchExpression(parser.parse(expression), parameters)); } /** @@ -64,11 +68,13 @@ public class QLMatchQuery<T> extends QLQuery<T> implements IMatchQuery<T> { } public IQueryResult<T> perform(Iterator<T> iterator) { - if (expression.needsTranslations()) { + if (QLUtil.needsTranslationSupport(expression)) { IQueryContext<T> queryContext = QL.newQueryContext(iterator); - context = expression.createContext(parameters, queryContext.getTranslationSupport(getLocale())); + IExpression translations = QLFactory.TRANSLATIONS; + context = EvaluationContext.create(expression.createContext(), translations); + context.setValue(translations, queryContext.getTranslationSupport(getLocale())); } else - context = expression.createContext(parameters); + context = expression.createContext(); prePerform(); try { diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/p2/ql/QLQuery.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/p2/ql/QLQuery.java index a39ecb61c..07ca483fb 100644 --- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/p2/ql/QLQuery.java +++ b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/p2/ql/QLQuery.java @@ -18,16 +18,12 @@ import org.eclipse.equinox.p2.query.IQuery; * An IQuery 'context query' implementation that is based on the p2 query language. */ public abstract class QLQuery<T> implements IQuery<T> { - static final IExpressionParser parser = QL.newParser(); - static final Object[] noParameters = new Object[0]; - + static final IQLParser parser = QL.newParser(); final Class<T> elementClass; - final Object[] parameters; private Locale locale; - protected QLQuery(Class<T> elementClass, Object[] parameters) { + protected QLQuery(Class<T> elementClass) { this.elementClass = elementClass; - this.parameters = parameters; } public Locale getLocale() { diff --git a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/p2/ql/QueryResult.java b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/p2/ql/QueryResult.java index e7ee396be..f42686912 100644 --- a/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/p2/ql/QueryResult.java +++ b/bundles/org.eclipse.equinox.p2.ql/src/org/eclipse/equinox/p2/ql/QueryResult.java @@ -3,8 +3,8 @@ package org.eclipse.equinox.p2.ql; import java.lang.reflect.Array; import java.util.*; import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.equinox.internal.p2.ql.IRepeatableIterator; -import org.eclipse.equinox.internal.p2.ql.RepeatableIterator; +import org.eclipse.equinox.internal.p2.metadata.expression.IRepeatableIterator; +import org.eclipse.equinox.internal.p2.metadata.expression.RepeatableIterator; import org.eclipse.equinox.p2.query.*; class QueryResult<T> implements IQueryResult<T> { |