Skip to content

Commit

Permalink
Correctly consider cardinality based on the directives
Browse files Browse the repository at this point in the history
Currently the BundlesAction uses either 0 or 1 as the cardinality but
actually a requirement can be a multi-cardinality as well.

This adds new dedicated methods to not duplicate the computation and a
testcase that ensures all combination are covered and correctly
translated.
  • Loading branch information
laeubi committed Feb 20, 2024
1 parent 151d95b commit 542fe65
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -398,10 +398,10 @@ protected void addRequirement(List<IRequirement> reqsDeps, GenericSpecification
Map<String, String> directives = req.getDirectives();

String capFilter = directives.get(Namespace.REQUIREMENT_FILTER_DIRECTIVE);
boolean optional = directives.get(Namespace.REQUIREMENT_RESOLUTION_DIRECTIVE) == Namespace.RESOLUTION_OPTIONAL;
boolean greedy = optional ? INSTALLATION_GREEDY.equals(directives.get(INSTALLATION_DIRECTIVE)) : true;

IRequirement requireCap = MetadataFactory.createRequirement(namespace, capFilter, null, optional ? 0 : 1, 1,
boolean greedy = isGreedy(directives);
int minCard = getMinCardinality(directives);
int maxCard = getMaxCardinality(directives);
IRequirement requireCap = MetadataFactory.createRequirement(namespace, capFilter, null, minCard, maxCard,
greedy);
reqsDeps.add(requireCap);
}
Expand All @@ -414,14 +414,31 @@ protected void addRequirement(List<IRequirement> reqsDeps, GenericSpecification
Map<String, String> directives = req.getDirectives();

String capFilter = directives.get(Namespace.REQUIREMENT_FILTER_DIRECTIVE);
boolean optional = directives.get(Namespace.REQUIREMENT_RESOLUTION_DIRECTIVE) == Namespace.RESOLUTION_OPTIONAL;
boolean greedy = optional ? INSTALLATION_GREEDY.equals(directives.get(INSTALLATION_DIRECTIVE)) : true;

IRequirement requireCap = MetadataFactory.createRequirement(namespace, capFilter, null, optional ? 0 : 1, 1,
boolean greedy = isGreedy(directives);
int minCard = getMinCardinality(directives);
int maxCard = getMaxCardinality(directives);
IRequirement requireCap = MetadataFactory.createRequirement(namespace, capFilter, null, minCard, maxCard,
greedy, bd.getSymbolicName());
reqsDeps.add(requireCap);
}

protected int getMinCardinality(Map<String, String> directives) {
return Namespace.RESOLUTION_OPTIONAL.equals(directives.get(Namespace.REQUIREMENT_RESOLUTION_DIRECTIVE)) ? 0 : 1;
}

protected int getMaxCardinality(Map<String, String> directives) {
return Namespace.CARDINALITY_MULTIPLE.equals(directives.get(Namespace.REQUIREMENT_CARDINALITY_DIRECTIVE))
? Integer.MAX_VALUE
: 1;
}

protected boolean isGreedy(Map<String, String> directives) {
if (getMinCardinality(directives) == 0) {
return INSTALLATION_GREEDY.equals(directives.get(INSTALLATION_DIRECTIVE));
}
return true;
}

protected void addCapability(List<IProvidedCapability> caps, GenericDescription provideCapDesc,
InstallableUnitDescription iu, int capNo) {
// Convert the values to String, Version, List of String or Version
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
import org.eclipse.equinox.internal.p2.metadata.ArtifactKey;
import org.eclipse.equinox.internal.p2.metadata.OSGiVersion;
import org.eclipse.equinox.internal.p2.metadata.RequiredCapability;
import org.eclipse.equinox.internal.p2.metadata.RequiredPropertiesMatch;
import org.eclipse.equinox.internal.p2.metadata.TranslationSupport;
import org.eclipse.equinox.p2.metadata.IArtifactKey;
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
Expand Down Expand Up @@ -515,6 +516,27 @@ public void testPublishBundlesWhereOneBundleIsInvalid() throws Exception {
assertThat(ius.size(), is(1));
}

public void testMultiRequired() throws Exception {
File testData = new File(TestActivator.getTestDataFolder(), "requireMultiple");
IInstallableUnit iu = BundlesAction.createBundleIU(BundlesAction.createBundleDescription(testData), null,
new PublisherInfo());
Map<String, List<RequiredPropertiesMatch>> map = iu.getRequirements().stream()
.filter(RequiredPropertiesMatch.class::isInstance)
.map(RequiredPropertiesMatch.class::cast)
.collect(Collectors.groupingBy(m -> RequiredPropertiesMatch.extractNamespace(m.getMatches())));
assertCardinality(map.get("single.required"), 1, 1);
assertCardinality(map.get("single.optional"), 0, 1);
assertCardinality(map.get("multiple.required"), 1, Integer.MAX_VALUE);
assertCardinality(map.get("multiple.optional"), 0, Integer.MAX_VALUE);
}

protected void assertCardinality(List<RequiredPropertiesMatch> matches, int min, int max) {
assertNotNull(matches);
assertEquals(1, matches.size());
assertEquals(min, matches.get(0).getMin());
assertEquals(max, matches.get(0).getMax());
}

public void testMultiVersionCapability() throws Exception {
File testData = getTestData("dymamicImport", "testData/multiVersionCapability/bundle1");
IInstallableUnit iu = BundlesAction.createBundleIU(BundlesAction.createBundleDescription(testData), null,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: require.multiple
Bundle-SymbolicName: require.multiple
Bundle-Version: 1.0.0
Require-Capability: single.required;filter:="(objectClass=testme)",
single.optional;filter:="(objectClass=testme)";resolution:=optional,
multiple.required;filter:="(objectClass=testme)";cardinality:=multiple,
multiple.optional;filter:="(objectClass=testme)";cardinality:=multiple;resolution:=optional

0 comments on commit 542fe65

Please sign in to comment.