private void pruneCoveredCaps()

in src/main/java/org/apache/sling/feature/apiregions/impl/ResolverHookImpl.java [254:304]


    private void pruneCoveredCaps(Set<String> reqRegions, Map<BundleCapability,String> capMap) {
        if (reqRegions == null) {
            // No regions (other than global) for the requirement: do nothing
            return;
        }

        Set<String> reqNonGlobalRegions = new HashSet<>(reqRegions);
        reqNonGlobalRegions.remove(RegionConstants.GLOBAL_REGION);

        if (capMap.size() <= 1) {
            // Shortcut: there is only 0 or 1 capability, nothing to do
            return;
        }

        List<BundleCapability> specificCaps = new ArrayList<>();
        for (Iterator<Map.Entry<BundleCapability,String>> it = capMap.entrySet().iterator(); it.hasNext(); ) {
            Map.Entry<BundleCapability,String> entry = it.next();

            String capRegion = entry.getValue();
            if (capRegion == null) {
                // This one came from the same bundle, the same feature or bundle 0 -> always allow
                specificCaps.add(entry.getKey());
                continue;
            }

            if (reqNonGlobalRegions.contains(capRegion)) {
                // the requirement has the region from the capability
                specificCaps.add(entry.getKey());
            }
        }

        if (specificCaps.size() == 0) {
            // There are no capabilities that are either in the same bundle, same feature or overlapping specific
            // feature. We should just allow all, including the global region
            return;
        }

        // There are specific capabilities, therefore we should remove the Global region is any from the capabilities
        // We have collected the capabilities we want to keep in specificCaps
        for (Iterator<BundleCapability> it = capMap.keySet().iterator(); it.hasNext(); ) {
            BundleCapability cap = it.next();
            if (!specificCaps.contains(cap)) {
                it.remove();
                Activator.LOG.log(Level.INFO, "Removing candidate {0} which is in region {1} as more specific candidate(s) are available in regions {2}",
                        new Object[] {
                                cap, capMap.get(cap),
                                specificCaps.stream().map(c -> "" + c + " region " + capMap.get(c)).collect(Collectors.joining("/"))
                        });
            }
        }
    }