diff options
Diffstat (limited to 'bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/RequiredCapability.java')
-rw-r--r-- | bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/RequiredCapability.java | 223 |
1 files changed, 139 insertions, 84 deletions
diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/RequiredCapability.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/RequiredCapability.java index ddee40c79..04d5b4ede 100644 --- a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/RequiredCapability.java +++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/RequiredCapability.java @@ -11,12 +11,10 @@ *******************************************************************************/ package org.eclipse.equinox.internal.p2.metadata; -import org.eclipse.equinox.p2.metadata.VersionRange; - import org.eclipse.core.runtime.Assert; import org.eclipse.equinox.p2.metadata.*; -import org.eclipse.equinox.p2.query.IQuery; -import org.eclipse.equinox.p2.query.MatchQuery; +import org.eclipse.equinox.p2.metadata.expression.*; +import org.osgi.framework.Filter; /** * A required capability represents some external constraint on an {@link IInstallableUnit}. @@ -31,80 +29,125 @@ import org.eclipse.equinox.p2.query.MatchQuery; * * @see IInstallableUnit#NAMESPACE_IU_ID */ -public class RequiredCapability extends MatchQuery<IInstallableUnit> implements IRequiredCapability, IRequirement { - private LDAPQuery filter; - private final String name;//never null - private final String namespace;//never null - private boolean greedy = true; - private final VersionRange range;//never null - private int min; - private int max; +public class RequiredCapability implements IRequiredCapability { + private final Filter filter; + private final boolean greedy; + private final IMatchExpression<IInstallableUnit> matchExpression; + private final int min; + private final int max; + + private static final String MEMBER_NAME = "name"; //$NON-NLS-1$ + private static final String MEMBER_NAMESPACE = "namespace"; //$NON-NLS-1$ + private static final String MEMBER_VERSION = "version"; //$NON-NLS-1$ + private static final String MEMBER_PROVIDED_CAPABILITIES = "providedCapabilities"; //$NON-NLS-1$ + + private static final IExpression allVersionsExpression; + private static final IExpression range_II_Expression; + private static final IExpression range_IN_Expression; + private static final IExpression range_NI_Expression; + private static final IExpression range_NN_Expression; + private static final IExpression strictVersionExpression; + private static final IExpression openEndedExpression; + private static final IExpression openEndedNonInclusiveExpression; + + static { + IExpressionFactory factory = ExpressionUtil.getFactory(); + IExpression xVar = factory.variable("x"); //$NON-NLS-1$ + IExpression nameEqual = factory.equals(factory.member(xVar, MEMBER_NAME), factory.indexedParameter(0)); + IExpression namespaceEqual = factory.equals(factory.member(xVar, MEMBER_NAMESPACE), factory.indexedParameter(1)); + + IExpression versionMember = factory.member(xVar, MEMBER_VERSION); + + IExpression versionCmpLow = factory.indexedParameter(2); + IExpression versionEqual = factory.equals(versionMember, versionCmpLow); + IExpression versionGt = factory.greater(versionMember, versionCmpLow); + IExpression versionGtEqual = factory.greaterEqual(versionMember, versionCmpLow); + + IExpression versionCmpHigh = factory.indexedParameter(3); + IExpression versionLt = factory.less(versionMember, versionCmpHigh); + IExpression versionLtEqual = factory.lessEqual(versionMember, versionCmpHigh); + + IExpression pvMember = factory.member(factory.thisVariable(), MEMBER_PROVIDED_CAPABILITIES); + allVersionsExpression = factory.exists(pvMember, factory.lambda(xVar, factory.and(nameEqual, namespaceEqual))); + strictVersionExpression = factory.exists(pvMember, factory.lambda(xVar, factory.and(nameEqual, namespaceEqual, versionEqual))); + openEndedExpression = factory.exists(pvMember, factory.lambda(xVar, factory.and(nameEqual, namespaceEqual, versionGtEqual))); + openEndedNonInclusiveExpression = factory.exists(pvMember, factory.lambda(xVar, factory.and(nameEqual, namespaceEqual, versionGt))); + range_II_Expression = factory.exists(pvMember, factory.lambda(xVar, factory.and(nameEqual, namespaceEqual, versionGtEqual, versionLtEqual))); + range_IN_Expression = factory.exists(pvMember, factory.lambda(xVar, factory.and(nameEqual, namespaceEqual, versionGtEqual, versionLt))); + range_NI_Expression = factory.exists(pvMember, factory.lambda(xVar, factory.and(nameEqual, namespaceEqual, versionGt, versionLtEqual))); + range_NN_Expression = factory.exists(pvMember, factory.lambda(xVar, factory.and(nameEqual, namespaceEqual, versionGt, versionLt))); + } /** * TODO replace booleans with int options flag. */ public RequiredCapability(String namespace, String name, VersionRange range, String filter, boolean optional, boolean multiple) { - Assert.isNotNull(namespace); - Assert.isNotNull(name); - this.namespace = namespace; - this.name = name; - this.range = range == null ? VersionRange.emptyRange : range; - min = optional ? 0 : 1; - max = 1; - setFilter(filter); + this(namespace, name, range, filter, optional, multiple, true); + } + + public RequiredCapability(String namespace, String name, VersionRange range, String filter, boolean optional, boolean multiple, boolean greedy) { + this(namespace, name, range, filter == null ? (Filter) null : ExpressionUtil.parseLDAP(filter), optional ? 0 : 1, multiple ? 1 : Integer.MAX_VALUE, greedy); } - public RequiredCapability(String namespace, String name, VersionRange range, IQuery<Boolean> filter, int min, int max, boolean greedy) { + public RequiredCapability(String namespace, String name, VersionRange range, Filter filter, int min, int max, boolean greedy) { Assert.isNotNull(namespace); Assert.isNotNull(name); - this.namespace = namespace; - this.name = name; - this.range = range == null ? VersionRange.emptyRange : range; - this.min = min; - this.max = max; - this.greedy = greedy; - if (filter != null) { - if (filter instanceof LDAPQuery) { - this.filter = (LDAPQuery) filter; + IExpressionFactory factory = ExpressionUtil.getFactory(); + if (range == null || range.equals(VersionRange.emptyRange)) { + matchExpression = factory.matchExpression(allVersionsExpression, name, namespace); + } else { + if (range.getMinimum().equals(range.getMaximum())) { + // Explicit version appointed + matchExpression = factory.matchExpression(strictVersionExpression, name, namespace, range.getMinimum()); } else { - throw new IllegalArgumentException(); + if (range.getMaximum().equals(Version.MAX_VERSION)) { + // Open ended + matchExpression = factory.matchExpression(range.getIncludeMinimum() ? openEndedExpression : openEndedNonInclusiveExpression, name, namespace, range.getMinimum()); + } else { + matchExpression = factory.matchExpression(// + range.getIncludeMinimum() ? (range.getIncludeMaximum() ? range_II_Expression : range_IN_Expression) // + : (range.getIncludeMaximum() ? range_NI_Expression : range_NN_Expression), // + name, namespace, range.getMinimum(), range.getMaximum()); + } } } - } - - public RequiredCapability(String namespace, String name, VersionRange range, String filter, boolean optional, boolean multiple, boolean greedy) { - this(namespace, name, range, filter, optional, multiple); + this.min = min; + this.max = max; this.greedy = greedy; + this.filter = filter; } public boolean equals(Object obj) { if (this == obj) return true; - if (obj == null) - return false; - if (!(obj instanceof IRequiredCapability)) - return false; - final IRequiredCapability other = (IRequiredCapability) obj; - if (filter == null) { - if (other.getFilter() != null) + if (obj instanceof RequiredCapability) { + RequiredCapability other = (RequiredCapability) obj; + if (filter == null) { + if (other.getFilter() != null) + return false; + } else if (!filter.equals(other.getFilter())) return false; - } else if (!filter.equals(other.getFilter())) - return false; - if (!name.equals(other.getName())) - return false; - if (!namespace.equals(other.getNamespace())) - return false; - if (!range.equals(other.getRange())) - return false; - return true; + return min == other.min && max == other.max && greedy == other.greedy && matchExpression.equals(other.matchExpression); + } + if (obj instanceof IRequiredCapability) { + // Some other type of RequiredCapability + IRequiredCapability other = (IRequiredCapability) obj; + if (filter == null) { + if (other.getFilter() != null) + return false; + } else if (!filter.equals(other.getFilter())) + return false; + return min == other.getMin() && max == other.getMax() && greedy == other.isGreedy() && getName().equals(other.getName()) && getNamespace().equals(other.getNamespace()) && getRange().equals(other.getRange()); + } + return false; } public String getName() { - return name; + return (String) matchExpression.getParameters()[0]; } public String getNamespace() { - return namespace; + return (String) matchExpression.getParameters()[1]; } /** @@ -114,28 +157,17 @@ public class RequiredCapability extends MatchQuery<IInstallableUnit> implements * @return the range of versions that satisfy this required capability. */ public VersionRange getRange() { - return range; + return extractRange(matchExpression); } public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((filter == null) ? 0 : filter.hashCode()); - result = prime * result + name.hashCode(); - result = prime * result + namespace.hashCode(); - result = prime * result + range.hashCode(); + result = prime * result + matchExpression.hashCode(); return result; } - /** - * TODO This object shouldn't be mutable since it makes equality unstable, and - * introduces lifecycle issues (how are the changes persisted, etc) - */ - public void setFilter(String filter) { - if (filter != null) - this.filter = new LDAPQuery(filter); - } - public boolean isGreedy() { return greedy; } @@ -157,6 +189,7 @@ public class RequiredCapability extends MatchQuery<IInstallableUnit> implements result.append(' '); result.append(getName()); result.append(' '); + VersionRange range = getRange(); //for an exact version match, print a simpler expression if (range.getMinimum().equals(range.getMaximum())) result.append('[').append(range.getMinimum()).append(']'); @@ -165,18 +198,6 @@ public class RequiredCapability extends MatchQuery<IInstallableUnit> implements return result.toString(); } - public boolean isNegation() { - return false; - } - - public boolean satisfiedBy(IProvidedCapability cap) { - if (getName() == null || !getName().equals(cap.getName())) - return false; - if (getNamespace() == null || !getNamespace().equals(cap.getNamespace())) - return false; - return getRange().isIncluded(cap.getVersion()); - } - public int getMin() { return min; } @@ -185,17 +206,51 @@ public class RequiredCapability extends MatchQuery<IInstallableUnit> implements return max; } - public IQuery<IInstallableUnit> getMatches() { - return this; + public IMatchExpression<IInstallableUnit> getMatches() { + return matchExpression; } - public IQuery<Boolean> getFilter() { + public Filter getFilter() { return filter; } public boolean isMatch(IInstallableUnit candidate) { - if (!candidate.satisfies(this)) - return false; - return true; + return matchExpression.isMatch(candidate); + } + + public static boolean isVersionStrict(IMatchExpression<IInstallableUnit> matchExpression) { + return ExpressionUtil.getOperand(matchExpression) == strictVersionExpression; + } + + public static String extractName(IMatchExpression<IInstallableUnit> matchExpression) { + assertValid(matchExpression); + return (String) matchExpression.getParameters()[0]; + } + + public static String extractNamespace(IMatchExpression<IInstallableUnit> matchExpression) { + assertValid(matchExpression); + return (String) matchExpression.getParameters()[1]; + } + + public static VersionRange extractRange(IMatchExpression<IInstallableUnit> matchExpression) { + IExpression expr = assertValid(matchExpression); + Object[] params = matchExpression.getParameters(); + if (params.length < 3) + return VersionRange.emptyRange; + Version v = (Version) params[2]; + if (params.length < 4) { + if (expr == strictVersionExpression) + return new VersionRange(v, true, v, true); + return new VersionRange(v, expr == openEndedExpression, Version.MAX_VERSION, true); + } + Version h = (Version) params[3]; + return new VersionRange(v, expr == range_II_Expression || expr == range_IN_Expression, h, expr == range_II_Expression || expr == range_NI_Expression); + } + + private static IExpression assertValid(IMatchExpression<IInstallableUnit> matchExpression) { + IExpression expr = ExpressionUtil.getOperand(matchExpression); + if (!(expr == allVersionsExpression || expr == range_II_Expression || expr == range_IN_Expression || expr == range_NI_Expression || expr == range_NN_Expression || expr == strictVersionExpression || expr == openEndedExpression || expr == openEndedNonInclusiveExpression)) + throw new IllegalArgumentException(); + return expr; } } |