Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clean-up, simplify and modernize Slicer, PermissiveSlicer ans SimplePlanner #349

Merged
merged 1 commit into from
Oct 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -14,94 +14,68 @@
package org.eclipse.equinox.internal.p2.director;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.eclipse.equinox.p2.metadata.*;
import org.eclipse.equinox.p2.query.QueryUtil;

public class AttachmentHelper {
private static final IInstallableUnitFragment[] NO_FRAGMENTS = new IInstallableUnitFragment[0];

public static Collection<IInstallableUnit> attachFragments(Iterator<IInstallableUnit> toAttach, Map<IInstallableUnitFragment, List<IInstallableUnit>> fragmentsToIUs) {
public static Collection<IInstallableUnit> attachFragments(Stream<IInstallableUnit> toAttach,
Map<IInstallableUnitFragment, List<IInstallableUnit>> fragmentsToIUs) {
Map<IInstallableUnit, IInstallableUnitFragment[]> fragmentBindings = new HashMap<>();
//Build a map inverse of the one provided in input (host --> List of fragments)
Map<IInstallableUnit, List<IInstallableUnitFragment>> iusToFragment = new HashMap<>(fragmentsToIUs.size());
for (Map.Entry<IInstallableUnitFragment, List<IInstallableUnit>> mapping : fragmentsToIUs.entrySet()) {
IInstallableUnitFragment fragment = mapping.getKey();
List<IInstallableUnit> existingMatches = mapping.getValue();

fragmentsToIUs.forEach((fragment, existingMatches) -> {
for (IInstallableUnit host : existingMatches) {
List<IInstallableUnitFragment> potentialFragments = iusToFragment.get(host);
if (potentialFragments == null) {
potentialFragments = new ArrayList<>();
iusToFragment.put(host, potentialFragments);
}
potentialFragments.add(fragment);
iusToFragment.computeIfAbsent(host, h -> new ArrayList<>()).add(fragment);
}
}
});

for (Map.Entry<IInstallableUnit, List<IInstallableUnitFragment>> entry : iusToFragment.entrySet()) {
IInstallableUnit hostIU = entry.getKey();
List<IInstallableUnitFragment> potentialIUFragments = entry.getValue();
ArrayList<IInstallableUnitFragment> applicableFragments = new ArrayList<>();
iusToFragment.forEach((hostIU, potentialIUFragments) -> {
List<IInstallableUnitFragment> applicableFragments = new ArrayList<>();
for (IInstallableUnitFragment potentialFragment : potentialIUFragments) {
if (hostIU.equals(potentialFragment))
if (hostIU.equals(potentialFragment)) {
continue;

}
// Check to make sure the host meets the requirements of the fragment
Collection<IRequirement> reqsFromFragment = potentialFragment.getHost();
boolean match = true;
boolean requirementMatched = false;
for (Iterator<IRequirement> iterator = reqsFromFragment.iterator(); iterator.hasNext() && match == true;) {
IRequirement reqs = iterator.next();
requirementMatched = false;
if (hostIU.satisfies(reqs))
requirementMatched = true;
if (requirementMatched == false) {
match = false;
break;
}

}
if (match) {
if (reqsFromFragment.stream().allMatch(hostIU::satisfies)) {
applicableFragments.add(potentialFragment);
}
}

IInstallableUnitFragment theFragment = null;
int specificityLevel = 0;
LinkedList<IInstallableUnitFragment> fragments = new LinkedList<>();
Deque<IInstallableUnitFragment> fragments = new LinkedList<>();
for (IInstallableUnitFragment fragment : applicableFragments) {
if (isTranslation(fragment)) {
fragments.add(fragment);
fragments.addLast(fragment);
continue;
}
if (fragment.getHost().size() > specificityLevel) {
theFragment = fragment;
specificityLevel = fragment.getHost().size();
}
}
if (theFragment != null)
if (theFragment != null) {
fragments.addFirst(theFragment);
if (!fragments.isEmpty())
fragmentBindings.put(hostIU, fragments.toArray(new IInstallableUnitFragment[fragments.size()]));
}
}
if (!fragments.isEmpty()) {
fragmentBindings.put(hostIU, fragments.toArray(IInstallableUnitFragment[]::new));
}
});
//build the collection of resolved IUs
Collection<IInstallableUnit> result = new HashSet<>();
while (toAttach.hasNext()) {
IInstallableUnit iu = toAttach.next();
if (iu == null)
continue;
return toAttach.filter(Objects::nonNull).map(iu -> {
//just return fragments as they are
if (QueryUtil.isFragment(iu)) {
result.add(iu);
continue;
return iu;
}
//return a new IU that combines the IU with its bound fragments
IInstallableUnitFragment[] fragments = fragmentBindings.get(iu);
if (fragments == null)
fragments = NO_FRAGMENTS;
result.add(MetadataFactory.createResolvedInstallableUnit(iu, fragments));
}
return result;
IInstallableUnitFragment[] fragments = fragmentBindings.getOrDefault(iu, NO_FRAGMENTS);
return MetadataFactory.createResolvedInstallableUnit(iu, fragments);
}).collect(Collectors.toCollection(HashSet::new));
}

private static boolean isTranslation(IInstallableUnitFragment fragment) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public List<WeightedObject<? extends Object>> createOptimizationFunction(IInstal
if (newRoots.isEmpty()) {
transitiveClosure = Collections.emptySet();
} else {
IQueryable<IInstallableUnit> queryable = new Slicer(picker, selectionContext, false).slice(newRoots.toArray(new IInstallableUnit[newRoots.size()]), new NullProgressMonitor());
IQueryable<IInstallableUnit> queryable = new Slicer(picker, selectionContext, false).slice(newRoots, null);
if (queryable == null) {
transitiveClosure = Collections.emptySet();
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import org.eclipse.equinox.internal.p2.metadata.RequiredCapability;
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
import org.eclipse.equinox.p2.metadata.IRequirement;
import org.eclipse.equinox.p2.metadata.expression.IMatchExpression;
import org.eclipse.equinox.p2.query.IQueryable;

public class PermissiveSlicer extends Slicer {
Expand All @@ -29,7 +30,7 @@ public class PermissiveSlicer extends Slicer {

public PermissiveSlicer(IQueryable<IInstallableUnit> input, Map<String, String> context, boolean includeOptionalDependencies, boolean everythingGreedy, boolean evalFilterTo, boolean considerOnlyStrictDependency, boolean onlyFilteredRequirements) {
super(input, context, true);
this.considerFilter = (context != null && context.size() > 1) ? true : false;
this.considerFilter = context != null && context.size() > 1;
this.includeOptionalDependencies = includeOptionalDependencies;
this.everythingGreedy = everythingGreedy;
this.evalFilterTo = evalFilterTo;
Expand All @@ -39,45 +40,31 @@ public PermissiveSlicer(IQueryable<IInstallableUnit> input, Map<String, String>

@Override
protected boolean isApplicable(IInstallableUnit iu) {
if (considerFilter)
if (considerFilter) {
return super.isApplicable(iu);
if (iu.getFilter() == null)
return true;
return evalFilterTo;
}
return iu.getFilter() == null || evalFilterTo;
}

@Override
protected boolean isApplicable(IRequirement req) {
//Every filter in this method needs to continue except when the filter does not pass
if (!includeOptionalDependencies)
if (req.getMin() == 0)
return false;

if (considerOnlyStrictDependency) {
if (!RequiredCapability.isStrictVersionRequirement(req.getMatches()))
return false;
if (!includeOptionalDependencies && req.getMin() == 0) {
return false;
}

//deal with filters
if (considerFilter) {
if (onlyFilteredRequirements && req.getFilter() == null) {
return false;
}
return super.isApplicable(req);
if (considerOnlyStrictDependency && !RequiredCapability.isStrictVersionRequirement(req.getMatches())) {
return false;
}
if (req.getFilter() == null) {
if (onlyFilteredRequirements)
return false;
return true;
//deal with filters
IMatchExpression<IInstallableUnit> filter = req.getFilter();
if (filter == null) {
return !onlyFilteredRequirements;
}
return evalFilterTo;
return considerFilter ? filter.isMatch(selectionContext) : evalFilterTo;
}

@Override
protected boolean isGreedy(IRequirement req) {
if (everythingGreedy) {
return true;
}
return super.isGreedy(req);
return everythingGreedy || super.isGreedy(req);
}
}
Loading
Loading