private Set<String> doResolveFeatures(Collection<String> rootFeatures, Set<String> preResolved, SelectionContext selectionContext) {
        // first pass; process the roots until we have selected all the candidates for multiple versions;
        // need to reset the initial black list count so we can recalculate it during the first pass
        selectionContext.resetInitialBlackListCount();
        Set<String> result = processCurrentPermutation(rootFeatures, preResolved, selectionContext);

        // if the first pass resulted in no conflicts return the results (optimistic)
        if (selectionContext.getResult().getConflicts().isEmpty()) {
            selectionContext.selectCurrentPermutation();
            return result;
        }

        // oh oh, we have conflicts;
        // NOTE, if the current solution has more conflicts than the initial count (black list)
        // then that means one of the toleration (postponed) choices we made introduced an
        // addition conflict.  That implies that a better solution may be available.
        // As long as there are more conflicts than the number of initial root conflicts
        // and there is a different permutation to try do another pass
        while (selectionContext.currentHasMoreThanInitialBlackListCount() && selectionContext.popPermutation()) {
            result = processCurrentPermutation(rootFeatures, preResolved, selectionContext);
        }

        // Return the best solution found
        selectionContext.restoreBestSolution();
        return selectionContext.getResult().getResolvedFeatures();
    }
private Set < String > doResolveFeatures ( Collection < String > rootFeatures , Set < String > preResolved , SelectionContext selectionContext ) { selectionContext . resetInitialBlackListCount ( ) ; Set < String > result = processCurrentPermutation ( rootFeatures , preResolved , selectionContext ) ; if ( selectionContext . getResult ( ) . getConflicts ( ) . isEmpty ( ) ) { selectionContext . selectCurrentPermutation ( ) ; return result ; } while ( selectionContext . currentHasMoreThanInitialBlackListCount ( ) && selectionContext . popPermutation ( ) ) { result = processCurrentPermutation ( rootFeatures , preResolved , selectionContext ) ; } selectionContext . restoreBestSolution ( ) ; return selectionContext . getResult ( ) . getResolvedFeatures ( ) ; }
/*
There are two phases to resolving the root features.
1) Optimistically process all multiple candidate features to the end picking the most preferred features
2) If this is successful then return the result with no conficts
3) If conflicts were found then backtrack over the permutations and choose different candidates. Note this may create more permutations
4) if a permutation is found that has not conflicts return the results
5) Otherwise use the first permutation and report the original conflicts