/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.felix.resolver;

import java.util.*;
import java.util.Map.Entry;
import java.util.concurrent.atomic.AtomicBoolean;

import org.apache.felix.resolver.ResolverImpl.PermutationType;
import org.apache.felix.resolver.ResolverImpl.ResolveSession;
import org.apache.felix.resolver.reason.ReasonException;
import org.apache.felix.resolver.util.*;
import org.osgi.framework.Version;
import org.osgi.framework.namespace.*;
import org.osgi.resource.*;
import org.osgi.service.resolver.HostedCapability;
import org.osgi.service.resolver.ResolutionException;
import org.osgi.service.resolver.ResolveContext;

class Candidates
{
    static class PopulateResult {
        boolean success;
        ResolutionError error;
        List<Requirement> remaining;
        Map<Requirement, List<Capability>> candidates;

        @Override
        public String toString() {
            return success ? "true" : error != null ? error.getMessage() : "???";
        }
    }

    private final ResolveSession m_session;
    // Maps a capability to requirements that match it.
    private final OpenHashMapSet<Capability, Requirement> m_dependentMap;
    // Maps a requirement to the capability it matches.
    private final OpenHashMapList m_candidateMap;
    // Maps a bundle revision to its associated wrapped revision; this only happens
    // when a revision being resolved has fragments to attach to it.
    private final Map<Resource, WrappedResource> m_allWrappedHosts;
    // Map used when populating candidates to hold intermediate and final results.
    private final OpenHashMap<Resource, PopulateResult> m_populateResultCache;

    private final Map<Capability, Requirement> m_subtitutableMap;

    private final OpenHashMapSet<Requirement, Capability> m_delta;
    private final AtomicBoolean m_candidateSelectorsUnmodifiable;

    /**
     * Private copy constructor used by the copy() method.
     */
    private Candidates(
        ResolveSession session,
        AtomicBoolean candidateSelectorsUnmodifiable,
        OpenHashMapSet<Capability, Requirement> dependentMap,
        OpenHashMapList candidateMap,
        Map<Resource, WrappedResource> wrappedHosts,
        OpenHashMap<Resource, PopulateResult> populateResultCache,
        Map<Capability, Requirement> substitutableMap,
        OpenHashMapSet<Requirement, Capability> delta)
    {
        m_session = session;
        m_candidateSelectorsUnmodifiable = candidateSelectorsUnmodifiable;
        m_dependentMap = dependentMap;
        m_candidateMap = candidateMap;
        m_allWrappedHosts = wrappedHosts;
        m_populateResultCache = populateResultCache;
        m_subtitutableMap = substitutableMap;
        m_delta = delta;
    }

    /**
     * Constructs an empty Candidates object.
     */
    public Candidates(ResolveSession session)
    {
        m_session = session;
        m_candidateSelectorsUnmodifiable = new AtomicBoolean(false);
        m_dependentMap = new OpenHashMapSet<Capability, Requirement>();
        m_candidateMap = new OpenHashMapList();
        m_allWrappedHosts = new HashMap<Resource, WrappedResource>();
        m_populateResultCache = new OpenHashMap<Resource, PopulateResult>();
        m_subtitutableMap = new OpenHashMap<Capability, Requirement>();
        m_delta = new OpenHashMapSet<Requirement, Capability>(3);
    }

    public int getNbResources()
    {
        return m_populateResultCache.size();
    }

    public Map<Resource, Resource> getRootHosts()
    {
        Map<Resource, Resource> hosts = new LinkedHashMap<Resource, Resource>();
        for (Resource res : m_session.getMandatoryResources())
        {
            addHost(res, hosts);
        }

        for (Resource res : m_session.getOptionalResources())
        {
            if (isPopulated(res)) {
                addHost(res, hosts);
            }
        }

        return hosts;
    }

    private void addHost(Resource res, Map<Resource, Resource> hosts) {
        if (res instanceof WrappedResource)
        {
            res = ((WrappedResource) res).getDeclaredResource();
        }
        if (!Util.isFragment(res))
        {
            hosts.put(res, getWrappedHost(res));
        } else {
            Requirement hostReq = res.getRequirements(HostNamespace.HOST_NAMESPACE).get(0);
            Capability hostCap = getFirstCandidate(hostReq);
            // If the resource is an already resolved fragment and can not
            // be attached to new hosts, there will be no matching host,
            // so ignore this resource
            if (hostCap != null) {
                res = getWrappedHost(hostCap.getResource());
                if (res instanceof WrappedResource) {
                    hosts.put(((WrappedResource) res).getDeclaredResource(), res);
                }
            }
        }
    }

    /**
     * Returns the delta which is the differences in the candidates from the
     * original Candidates permutation.
     * @return the delta
     */
    public Object getDelta()
    {
        return m_delta;
    }

    public void populate(Collection<Resource> resources)
    {
        ResolveContext rc = m_session.getContext();
        Set<Resource> toRemove = new HashSet<Resource>();
        LinkedList<Resource> toPopulate = new LinkedList<Resource>(resources);
        while (!toPopulate.isEmpty())
        {
            Resource resource = toPopulate.getFirst();
            // Get cached result
            PopulateResult result = m_populateResultCache.get(resource);
            if (result == null)
            {
                result = new PopulateResult();
                result.candidates = new OpenHashMap<Requirement, List<Capability>>();
                result.remaining = new ArrayList<Requirement>(resource.getRequirements(null));
                m_populateResultCache.put(resource, result);
            }
            if (result.success || result.error != null)
            {
                toPopulate.removeFirst();
                continue;
            }
            if (result.remaining.isEmpty())
            {
                toPopulate.removeFirst();
                result.success = true;
                addCandidates(result.candidates);
                result.candidates = null;
                result.remaining = null;
                Collection<Resource> relatedResources = rc.findRelatedResources(resource);
                m_session.setRelatedResources(resource, relatedResources);
                for (Resource relatedResource : relatedResources)
                {
                    if (m_session.isValidRelatedResource(relatedResource))
                    {
                        // This resource is a valid related resource;
                        // populate it now, consider it optional
                        toPopulate.addFirst(relatedResource);
                    }
                }
                continue;
            }
            // We have a requirement to process
            Requirement requirement = result.remaining.remove(0);
            if (!isEffective(requirement))
            {
                continue;
            }
            List<Capability> candidates = rc.findProviders(requirement);
            LinkedList<Resource> newToPopulate = new LinkedList<Resource>();
            ResolutionError thrown = processCandidates(newToPopulate, requirement, candidates);
             if (candidates.isEmpty() && !Util.isOptional(requirement))
            {
                if (Util.isFragment(resource) && rc.getWirings().containsKey(resource))
                {
                    // This is a fragment that is already resolved and there is no unresolved hosts to attach it to.
                    result.success = true;
                }
                else
                {
                    result.error = new MissingRequirementError(requirement, thrown);
                    toRemove.add(resource);
                }
                toPopulate.removeFirst();
            }
            else
            {
                if (!candidates.isEmpty())
                {
                    result.candidates.put(requirement, candidates);
                }
                if (!newToPopulate.isEmpty())
                {
                    toPopulate.addAll(0, newToPopulate);
                }
            }
        }

        while (!toRemove.isEmpty())
        {
            Iterator<Resource> iterator = toRemove.iterator();
            Resource resource = iterator.next();
            iterator.remove();
            remove(resource, toRemove);
        }
    }

    private boolean isEffective(Requirement req) {
        if (!m_session.getContext().isEffective(req)) {
            return false;
        }
        String res = req.getDirectives().get(PackageNamespace.REQUIREMENT_RESOLUTION_DIRECTIVE);
        return !PackageNamespace.RESOLUTION_DYNAMIC.equals(res);
    }

    private void populateSubstitutables()
    {
        for (Map.Entry<Resource, PopulateResult> populated : m_populateResultCache.fast())
        {
            if (populated.getValue().success)
            {
                populateSubstitutables(populated.getKey());
            }
        }
    }

    private void populateSubstitutables(Resource resource)
    {
        // Collect the package names exported
        @SuppressWarnings("serial")
        OpenHashMap<String, List<Capability>> exportNames = new OpenHashMap<String, List<Capability>>() {
            @Override
            protected List<Capability> compute(String s) {
                return new ArrayList<Capability>(1);
            }
        };
        for (Capability packageExport : resource.getCapabilities(null))
        {
            if (!PackageNamespace.PACKAGE_NAMESPACE.equals(packageExport.getNamespace()))
            {
                continue;
            }
            String packageName = (String) packageExport.getAttributes().get(PackageNamespace.PACKAGE_NAMESPACE);
            List<Capability> caps = exportNames.getOrCompute(packageName);
            caps.add(packageExport);
        }
        if (exportNames.isEmpty())
        {
            return;
        }
        // Check if any requirements substitute one of the exported packages
        for (Requirement req : resource.getRequirements(null))
        {
            if (!PackageNamespace.PACKAGE_NAMESPACE.equals(req.getNamespace()))
            {
                continue;
            }
            CandidateSelector substitutes = m_candidateMap.get(req);
            if (substitutes != null && !substitutes.isEmpty())
            {
                String packageName = (String) substitutes.getCurrentCandidate().getAttributes().get(PackageNamespace.PACKAGE_NAMESPACE);
                List<Capability> exportedPackages = exportNames.get(packageName);
                if (exportedPackages != null)
                {
                    // The package is exported;
                    // Check if the requirement only has the bundle's own export as candidates
                    if (!exportedPackages.containsAll(substitutes.getRemainingCandidates()))
                    {
                        for (Capability exportedPackage : exportedPackages)
                        {
                            m_subtitutableMap.put(exportedPackage, req);
                        }
                    }
                }
            }
        }
    }

    private static final int UNPROCESSED = 0;
    private static final int PROCESSING = 1;
    private static final int SUBSTITUTED = 2;
    private static final int EXPORTED = 3;

    ResolutionError checkSubstitutes()
    {
        OpenHashMap<Capability, Integer> substituteStatuses = new OpenHashMap<Capability, Integer>(m_subtitutableMap.size());
        for (Capability substitutable : m_subtitutableMap.keySet())
        {
            // initialize with unprocessed
            substituteStatuses.put(substitutable, UNPROCESSED);
        }
        // note we are iterating over the original unmodified map by design
        for (Capability substitutable : m_subtitutableMap.keySet())
        {
            isSubstituted(substitutable, substituteStatuses);
        }

        // Remove any substituted exports from candidates
        for (Map.Entry<Capability, Integer> substituteStatus : substituteStatuses.fast())
        {
            // add a permutation that imports a different candidate for the substituted if possible
            Requirement substitutedReq = m_subtitutableMap.get(substituteStatus.getKey());
            if (substitutedReq != null)
            {
                m_session.permutateIfNeeded(PermutationType.SUBSTITUTE, substitutedReq, this);
            }
            Set<Requirement> dependents = m_dependentMap.get(substituteStatus.getKey());
            if (dependents != null)
            {
                for (Requirement dependent : dependents)
                {
                    CandidateSelector candidates = m_candidateMap.get(dependent);
                    if (candidates != null)
                    {
                        candidates:
                        while (!candidates.isEmpty())
                        {
                            Capability candidate = candidates.getCurrentCandidate();
                            Integer candidateStatus = substituteStatuses.get(candidate);
                            if (candidateStatus == null)
                            {
                                candidateStatus = EXPORTED;
                            }
                            switch (candidateStatus)
                            {
                                case EXPORTED:
                                    // non-substituted candidate hit before the substituted one; do not continue
                                    break candidates;
                                case SUBSTITUTED:
                                default:
                                    // Need to remove any substituted that comes before an exported candidate
                                    candidates.removeCurrentCandidate();
                                    // continue to next candidate
                                    break;
                            }
                        }
                        if (candidates.isEmpty())
                        {
                            if (Util.isOptional(dependent))
                            {
                                m_candidateMap.remove(dependent);
                            }
                            else
                            {
                                return new MissingRequirementError(dependent);
                            }
                        }
                    }
                }
            }
        }
        return null;
    }

    private boolean isSubstituted(Capability substitutableCap, Map<Capability, Integer> substituteStatuses)
    {
        Integer substituteState = substituteStatuses.get(substitutableCap);
        if (substituteState == null)
        {
            return false;
        }

        switch (substituteState)
        {
            case PROCESSING:
                // found a cycle mark the initiator as not substituted
                substituteStatuses.put(substitutableCap, EXPORTED);
                return false;
            case SUBSTITUTED:
                return true;
            case EXPORTED:
                return false;
            default:
                break;
        }

        Requirement substitutableReq = m_subtitutableMap.get(substitutableCap);
        if (substitutableReq == null)
        {
            // this should never happen.
            return false;
        }
        // mark as processing to detect cycles
        substituteStatuses.put(substitutableCap, PROCESSING);
        // discover possible substitutes
        CandidateSelector substitutes = m_candidateMap.get(substitutableReq);
        if (substitutes != null)
        {
            for (Capability substituteCandidate : substitutes.getRemainingCandidates())
            {
                if (substituteCandidate.getResource().equals(substitutableCap.getResource()))
                {
                    substituteStatuses.put(substitutableCap, EXPORTED);
                    return false;
                }
                if (!isSubstituted(substituteCandidate, substituteStatuses))
                {
                    // The resource's exported package is substituted for this permutation.
                    substituteStatuses.put(substitutableCap, SUBSTITUTED);
                    return true;
                }
            }
        }
        // if we get here then the export is not substituted
        substituteStatuses.put(substitutableCap, EXPORTED);
        return false;
    }

    public ResolutionError populateDynamic()
    {

        // Process the candidates, removing any candidates that
        // cannot resolve.
        // TODO: verify the two following statements
        LinkedList<Resource> toPopulate = new LinkedList<Resource>();
        ResolutionError rethrow = processCandidates(toPopulate, m_session.getDynamicRequirement(), m_session.getDynamicCandidates());

        // Add the dynamic imports candidates.
        // Make sure this is done after the call to processCandidates since we want to ensure
        // fragment candidates are properly hosted before adding the candidates list which makes a copy
        addCandidates(m_session.getDynamicRequirement(), m_session.getDynamicCandidates());

        populate(toPopulate);

        CandidateSelector caps = m_candidateMap.get(m_session.getDynamicRequirement());
        if (caps != null)
        {
            m_session.getDynamicCandidates().retainAll(caps.getRemainingCandidates());
        }
        else
        {
            m_session.getDynamicCandidates().clear();
        }

        if (m_session.getDynamicCandidates().isEmpty())
        {
            if (rethrow == null)
            {
                rethrow = new DynamicImportFailed(m_session.getDynamicRequirement());
            }
            return rethrow;
        }

        PopulateResult result = new PopulateResult();
        result.success = true;
        m_populateResultCache.put(m_session.getDynamicHost(), result);
        return null;
    }

    private ResolutionError processCandidates(
        LinkedList<Resource> toPopulate,
        Requirement req,
        List<Capability> candidates)
    {
        ResolveContext rc = m_session.getContext();
        // Get satisfying candidates and populate their candidates if necessary.
        ResolutionError rethrow = null;
        Set<Capability> fragmentCands = null;
        for (Iterator<Capability> itCandCap = candidates.iterator();
            itCandCap.hasNext();)
        {
            Capability candCap = itCandCap.next();

            boolean isFragment = Util.isFragment(candCap.getResource());

            // If the capability is from a fragment, then record it
            // because we have to insert associated host capabilities
            // if the fragment is already attached to any hosts.
            if (isFragment)
            {
                if (fragmentCands == null)
                {
                    fragmentCands = new HashSet<Capability>();
                }
                fragmentCands.add(candCap);
            }

            // Do a sanity check incase the resolve context tries to attach
            // a fragment to an already resolved host capability
            if (HostNamespace.HOST_NAMESPACE.equals(req.getNamespace())) {
                if (rc.getWirings().containsKey(candCap.getResource())) {
                    itCandCap.remove();
                    continue;
                }
            }
            // If the candidate revision is a fragment, then always attempt
            // to populate candidates for its dependency, since it must be
            // attached to a host to be used. Otherwise, if the candidate
            // revision is not already resolved and is not the current version
            // we are trying to populate, then populate the candidates for
            // its dependencies as well.
            // NOTE: Technically, we don't have to check to see if the
            // candidate revision is equal to the current revision, but this
            // saves us from recursing and also simplifies exceptions messages
            // since we effectively chain exception messages for each level
            // of recursion; thus, any avoided recursion results in fewer
            // exceptions to chain when an error does occur.
            if ((isFragment || !rc.getWirings().containsKey(candCap.getResource()))
                && !candCap.getResource().equals(req.getResource()))
            {
                PopulateResult result = m_populateResultCache.get(candCap.getResource());
                if (result != null)
                {
                    if (result.error != null)
                    {
                        if (rethrow == null)
                        {
                            rethrow = result.error;
                        }
                        // Remove the candidate since we weren't able to
                        // populate its candidates.
                        itCandCap.remove();
                    }
                    else if (!result.success)
                    {
                        toPopulate.add(candCap.getResource());
                    }
                }
                else
                {
                    toPopulate.add(candCap.getResource());
                }
            }
        }

        // If any of the candidates for the requirement were from a fragment,
        // then also insert synthesized hosted capabilities for any other host
        // to which the fragment is attached since they are all effectively
        // unique capabilities.
        if (fragmentCands != null)
        {
            for (Capability fragCand : fragmentCands)
            {
                String fragCandName = fragCand.getNamespace();
                if (IdentityNamespace.IDENTITY_NAMESPACE.equals(fragCandName))
                {
                    // no need to wrap identity namespace ever
                    continue;
                }
                // Only necessary for resolved fragments.
                Wiring wiring = rc.getWirings().get(fragCand.getResource());
                if (wiring != null)
                {
                    // Fragments only have host wire, so each wire represents
                    // an attached host.
                    for (Wire wire : wiring.getRequiredResourceWires(HostNamespace.HOST_NAMESPACE))
                    {
                        // If the capability is a package, then make sure the
                        // host actually provides it in its resolved capabilities,
                        // since it may be a substitutable export.
                        if (!fragCandName.equals(PackageNamespace.PACKAGE_NAMESPACE)
                            || rc.getWirings().get(wire.getProvider())
                            .getResourceCapabilities(null).contains(fragCand))
                        {
                            // Note that we can just add this as a candidate
                            // directly, since we know it is already resolved.
                            // NOTE: We are synthesizing a hosted capability here,
                            // but we are not using a ShadowList like we do when
                            // we synthesizing capabilities for unresolved hosts.
                            // It is not necessary to use the ShadowList here since
                            // the host is resolved, because in that case we can
                            // calculate the proper package space by traversing
                            // the wiring. In the unresolved case, this isn't possible
                            // so we need to use the ShadowList so we can keep
                            // a reference to a synthesized resource with attached
                            // fragments so we can correctly calculate its package
                            // space.
                            // Must remove the fragment candidate because we must
                            // only use hosted capabilities for package namespace
                            candidates.remove(fragCand);
                            rc.insertHostedCapability(
                                candidates,
                                new WrappedCapability(
                                    wire.getCapability().getResource(),
                                    fragCand));
                        }
                    }
                }
            }
        }

        return rethrow;
    }

    public boolean isPopulated(Resource resource)
    {
        PopulateResult value = m_populateResultCache.get(resource);
        return (value != null && value.success);
    }

    public ResolutionError getResolutionError(Resource resource)
    {
        PopulateResult value = m_populateResultCache.get(resource);
        return value != null ? value.error : null;
    }

    /**
     * Adds a requirement and its matching candidates to the internal data
     * structure. This method assumes it owns the data being passed in and does
     * not make a copy. It takes the data and processes, such as calculating
     * which requirements depend on which capabilities and recording any
     * fragments it finds for future merging.
     *
     * @param req the requirement to add.
     * @param candidates the candidates matching the requirement.
     */
    private void addCandidates(Requirement req, List<Capability> candidates)
    {
        // Record the candidates.
        m_candidateMap.put(req, new CandidateSelector(candidates, m_candidateSelectorsUnmodifiable));
        for (Capability cap : candidates)
        {
            m_dependentMap.getOrCompute(cap).add(req);
        }
    }

    /**
     * Adds requirements and candidates in bulk. The outer map is not retained
     * by this method, but the inner data structures are, so they should not be
     * further modified by the caller.
     *
     * @param candidates the bulk requirements and candidates to add.
     */
    private void addCandidates(Map<Requirement, List<Capability>> candidates)
    {
        for (Map.Entry<Requirement, List<Capability>> entry : candidates.entrySet())
        {
            addCandidates(entry.getKey(), entry.getValue());
        }
    }

    /**
     * Returns the wrapped resource associated with the given resource. If the
     * resource was not wrapped, then the resource itself is returned. This is
     * really only needed to determine if the root resources of the resolve have
     * been wrapped.
     *
     * @param r the resource whose wrapper is desired.
     * @return the wrapper resource or the resource itself if it was not
     * wrapped.
     */
    public Resource getWrappedHost(Resource r)
    {
        Resource wrapped = m_allWrappedHosts.get(r);
        return (wrapped == null) ? r : wrapped;
    }

    /**
     * Gets the candidates associated with a given requirement.
     *
     * @param req the requirement whose candidates are desired.
     * @return the matching candidates or null.
     */
    public List<Capability> getCandidates(Requirement req)
    {
        CandidateSelector candidates = m_candidateMap.get(req);
        if (candidates != null)
        {
            return candidates.getRemainingCandidates();
        }
        return null;
    }

    public Capability getFirstCandidate(Requirement req)
    {
        CandidateSelector candidates = m_candidateMap.get(req);
        if (candidates != null && !candidates.isEmpty())
        {
            return candidates.getCurrentCandidate();
        }
        return null;
    }

    public void removeFirstCandidate(Requirement req)
    {
        CandidateSelector candidates = m_candidateMap.get(req);
        // Remove the conflicting candidate.
        Capability cap = candidates.removeCurrentCandidate();
        if (candidates.isEmpty())
        {
            m_candidateMap.remove(req);
        }
        // Update the delta with the removed capability
        CopyOnWriteSet<Capability> capPath = m_delta.getOrCompute(req);
        capPath.add(cap);
    }

    public CandidateSelector clearMultipleCardinalityCandidates(Requirement req, Collection<Capability> caps)
    {
        // this is a special case where we need to completely replace the CandidateSelector
        // this method should never be called from normal Candidates permutations
        CandidateSelector candidates = m_candidateMap.get(req);
        List<Capability> remaining = new ArrayList<Capability>(candidates.getRemainingCandidates());
        remaining.removeAll(caps);
        candidates = new CandidateSelector(remaining, m_candidateSelectorsUnmodifiable);
        m_candidateMap.put(req, candidates);
        return candidates;
    }

    /**
     * Merges fragments into their hosts. It does this by wrapping all host
     * modules and attaching their selected fragments, removing all unselected
     * fragment modules, and replacing all occurrences of the original fragments
     * in the internal data structures with the wrapped host modules instead.
     * Thus, fragment capabilities and requirements are merged into the
     * appropriate host and the candidates for the fragment now become
     * candidates for the host. Likewise, any module depending on a fragment now
     * depend on the host. Note that this process is sort of like
     * multiplication, since one fragment that can attach to two hosts
     * effectively gets multiplied across the two hosts. So, any modules being
     * satisfied by the fragment will end up having the two hosts as potential
     * candidates, rather than the single fragment.
     *
     * @return  ResolutionError if the removal of any unselected fragments
     * result in the root module being unable to resolve.
     */
    public ResolutionError prepare()
    {
        // Maps a host capability to a map containing its potential fragments;
        // the fragment map maps a fragment symbolic name to a map that maps
        // a version to a list of fragments requirements matching that symbolic
        // name and version.
        Map<Capability, Map<String, Map<Version, List<Requirement>>>> hostFragments =
            getHostFragments();

        // This method performs the following steps:
        // 1. Select the fragments to attach to a given host.
        // 2. Wrap hosts and attach fragments.
        // 3. Remove any unselected fragments. This is necessary because
        //    other revisions may depend on the capabilities of unselected
        //    fragments, so we need to remove the unselected fragments and
        //    any revisions that depends on them, which could ultimately cause
        //    the entire resolve to fail.
        // 4. Replace all fragments with any host it was merged into
        //    (effectively multiplying it).
        //    * This includes setting candidates for attached fragment
        //      requirements as well as replacing fragment capabilities
        //      with host's attached fragment capabilities.
        // Steps 1 and 2
        List<WrappedResource> hostResources = new ArrayList<WrappedResource>();
        List<Resource> unselectedFragments = new ArrayList<Resource>();
        for (Entry<Capability, Map<String, Map<Version, List<Requirement>>>> hostEntry : hostFragments.entrySet())
        {
            // Step 1
            Capability hostCap = hostEntry.getKey();
            Map<String, Map<Version, List<Requirement>>> fragments =
                hostEntry.getValue();
            List<Resource> selectedFragments = new ArrayList<Resource>();
            for (Entry<String, Map<Version, List<Requirement>>> fragEntry
                : fragments.entrySet())
            {
                boolean isFirst = true;
                for (Entry<Version, List<Requirement>> versionEntry
                    : fragEntry.getValue().entrySet())
                {
                    for (Requirement hostReq : versionEntry.getValue())
                    {
                        // Selecting the first fragment in each entry, which
                        // is equivalent to selecting the highest version of
                        // each fragment with a given symbolic name.
                        if (isFirst)
                        {
                            selectedFragments.add(hostReq.getResource());
                            isFirst = false;
                        }
                        // For any fragment that wasn't selected, remove the
                        // current host as a potential host for it and remove it
                        // as a dependent on the host. If there are no more
                        // potential hosts for the fragment, then mark it as
                        // unselected for later removal.
                        else
                        {
                            m_dependentMap.get(hostCap).remove(hostReq);
                            CandidateSelector hosts = removeCandidate(hostReq, hostCap);
                            if (hosts.isEmpty())
                            {
                                unselectedFragments.add(hostReq.getResource());
                            }
                        }
                    }
                }
            }

            // Step 2
            WrappedResource wrappedHost =
                new WrappedResource(hostCap.getResource(), selectedFragments);
            hostResources.add(wrappedHost);
            m_allWrappedHosts.put(hostCap.getResource(), wrappedHost);
        }

        // Step 3
        for (Resource fragment : unselectedFragments)
        {
            removeResource(fragment, new FragmentNotSelectedError(fragment));
        }

        // Step 4
        // First copy candidates for wrapped requirements to the host.
        for (WrappedResource hostResource : hostResources) {
            for (Requirement r : hostResource.getRequirements(null))
            {
                Requirement origReq = ((WrappedRequirement) r).getDeclaredRequirement();
                CandidateSelector cands = m_candidateMap.get(origReq);
                if (cands != null)
                {
                    if (cands instanceof ShadowList)
                    {
                        m_candidateMap.put(r, ShadowList.deepCopy((ShadowList) cands));
                    } else {
                        m_candidateMap.put(r, cands.copy());
                    }
                    for (Capability cand : cands.getRemainingCandidates())
                    {
                        Set<Requirement> dependents = m_dependentMap.get(cand);
                        dependents.remove(origReq);
                        dependents.add(r);
                    }
                }
            }
        }

        for (WrappedResource hostResource : hostResources)
        {
            // Replaces capabilities from fragments with the capabilities
            // from the merged host.
            for (Capability c : hostResource.getCapabilities(null))
            {
                // Don't replace the host capability, since the fragment will
                // really be attached to the original host, not the wrapper.
                if (!c.getNamespace().equals(HostNamespace.HOST_NAMESPACE))
                {
                    Capability origCap = ((HostedCapability) c).getDeclaredCapability();
                    // Note that you might think we could remove the original cap
                    // from the dependent map, but you can't since it may come from
                    // a fragment that is attached to multiple hosts, so each host
                    // will need to make their own copy.
                    CopyOnWriteSet<Requirement> dependents = m_dependentMap.get(origCap);
                    if (dependents != null)
                    {
                        dependents = new CopyOnWriteSet<Requirement>(dependents);
                        m_dependentMap.put(c, dependents);
                        for (Requirement r : dependents)
                        {
                            // We have synthesized hosted capabilities for all
                            // fragments that have been attached to hosts by
                            // wrapping the host bundle and their attached
                            // fragments. We need to use the ResolveContext to
                            // determine the proper priority order for hosted
                            // capabilities since the order may depend on the
                            // declaring host/fragment combination. However,
                            // internally we completely wrap the host revision
                            // and make all capabilities/requirements point back
                            // to the wrapped host not the declaring host. The
                            // ResolveContext expects HostedCapabilities to point
                            // to the declaring revision, so we need two separate
                            // candidate lists: one for the ResolveContext with
                            // HostedCapabilities pointing back to the declaring
                            // host and one for the resolver with HostedCapabilities
                            // pointing back to the wrapped host. We ask the
                            // ResolveContext to insert its appropriate HostedCapability
                            // into its list, then we mirror the insert into a
                            // shadow list with the resolver's HostedCapability.
                            // We only need to ask the ResolveContext to find
                            // the insert position for fragment caps since these
                            // were synthesized and we don't know their priority.
                            // However, in the resolver's candidate list we need
                            // to replace all caps with the wrapped caps, no
                            // matter if they come from the host or fragment,
                            // since we are completing replacing the declaring
                            // host and fragments with the wrapped host.
                            CandidateSelector cands = m_candidateMap.get(r);
                            ShadowList shadow;
                            if (!(cands instanceof ShadowList))
                            {
                                shadow = ShadowList.createShadowList(cands);
                                m_candidateMap.put(r, shadow);
                                cands = shadow;
                            }
                            else
                            {
                                shadow = (ShadowList) cands;
                            }

                            // If the original capability is from a fragment, then
                            // ask the ResolveContext to insert it and update the
                            // shadow copy of the list accordingly.
                            if (!origCap.getResource().equals(hostResource.getDeclaredResource()))
                            {
                                shadow.insertHostedCapability(
                                        m_session.getContext(),
                                        (HostedCapability) c,
                                        new SimpleHostedCapability(
                                                hostResource.getDeclaredResource(),
                                                origCap));
                            }
                            // If the original capability is from the host, then
                            // we just need to replace it in the shadow list.
                            else
                            {
                                shadow.replace(origCap, c);
                            }
                        }
                    }
                }
            }
        }

        // Lastly, verify that all mandatory revisions are still
        // populated, since some might have become unresolved after
        // selecting fragments/singletons.
        for (Resource resource : m_session.getMandatoryResources())
        {
            if (!isPopulated(resource))
            {
                return getResolutionError(resource);
            }
        }

        populateSubstitutables();

        m_candidateMap.trim();
        m_dependentMap.trim();

        // mark the selectors as unmodifiable now
        m_candidateSelectorsUnmodifiable.set(true);
        return null;
    }

    // Maps a host capability to a map containing its potential fragments;
    // the fragment map maps a fragment symbolic name to a map that maps
    // a version to a list of fragments requirements matching that symbolic
    // name and version.
    private Map<Capability, Map<String, Map<Version, List<Requirement>>>> getHostFragments()
    {
        Map<Capability, Map<String, Map<Version, List<Requirement>>>> hostFragments =
            new HashMap<Capability, Map<String, Map<Version, List<Requirement>>>>();
        for (Entry<Requirement, CandidateSelector> entry : m_candidateMap.fast())
        {
            Requirement req = entry.getKey();
            CandidateSelector caps = entry.getValue();
            for (Capability cap : caps.getRemainingCandidates())
            {
                // Keep track of hosts and associated fragments.
                if (req.getNamespace().equals(HostNamespace.HOST_NAMESPACE))
                {
                    String resSymName = Util.getSymbolicName(req.getResource());
                    Version resVersion = Util.getVersion(req.getResource());

                    Map<String, Map<Version, List<Requirement>>> fragments = hostFragments.get(cap);
                    if (fragments == null)
                    {
                        fragments = new HashMap<String, Map<Version, List<Requirement>>>();
                        hostFragments.put(cap, fragments);
                    }
                    Map<Version, List<Requirement>> fragmentVersions = fragments.get(resSymName);
                    if (fragmentVersions == null)
                    {
                        fragmentVersions =
                            new TreeMap<Version, List<Requirement>>(Collections.reverseOrder());
                        fragments.put(resSymName, fragmentVersions);
                    }
                    List<Requirement> actual = fragmentVersions.get(resVersion);
                    if (actual == null)
                    {
                        actual = new ArrayList<Requirement>();
                        if (resVersion == null)
                            resVersion = new Version(0, 0, 0);
                        fragmentVersions.put(resVersion, actual);
                    }
                    actual.add(req);
                }
            }
        }

        return hostFragments;
    }

    /**
     * Removes a module from the internal data structures if it wasn't selected
     * as a fragment or a singleton. This process may cause other modules to
     * become unresolved if they depended on the module's capabilities and there
     * is no other candidate.
     *
     * @param resource the module to remove.
     * @param ex the resolution error
     */
    private void removeResource(Resource resource, ResolutionError ex)
    {
        // Add removal reason to result cache.
        PopulateResult result = m_populateResultCache.get(resource);
        result.success = false;
        result.error = ex;
        // Remove from dependents.
        Set<Resource> unresolvedResources = new HashSet<Resource>();
        remove(resource, unresolvedResources);
        // Remove dependents that failed as a result of removing revision.
        while (!unresolvedResources.isEmpty())
        {
            Iterator<Resource> it = unresolvedResources.iterator();
            resource = it.next();
            it.remove();
            remove(resource, unresolvedResources);
        }
    }

    /**
     * Removes the specified module from the internal data structures, which
     * involves removing its requirements and its capabilities. This may cause
     * other modules to become unresolved as a result.
     *
     * @param resource the module to remove.
     * @param unresolvedResources a list to containing any additional modules
     * that that became unresolved as a result of removing this module and will
     * also need to be removed.
     */
    private void remove(Resource resource, Set<Resource> unresolvedResources)
    {
        for (Requirement r : resource.getRequirements(null))
        {
            remove(r);
        }

        for (Capability c : resource.getCapabilities(null))
        {
            remove(c, unresolvedResources);
        }
    }

    /**
     * Removes a requirement from the internal data structures.
     *
     * @param req the requirement to remove.
     */
    private void remove(Requirement req)
    {
        CandidateSelector candidates = m_candidateMap.remove(req);
        if (candidates != null)
        {
            for (Capability cap : candidates.getRemainingCandidates())
            {
                Set<Requirement> dependents = m_dependentMap.get(cap);
                if (dependents != null)
                {
                    dependents.remove(req);
                }
            }
        }
    }

    /**
     * Removes a capability from the internal data structures. This may cause
     * other modules to become unresolved as a result.
     *
     * @param c the capability to remove.
     * @param unresolvedResources a list to containing any additional modules
     * that that became unresolved as a result of removing this module and will
     * also need to be removed.
     */
    private void remove(Capability c, Set<Resource> unresolvedResources)
    {
        Set<Requirement> dependents = m_dependentMap.remove(c);
        if (dependents != null)
        {
            for (Requirement r : dependents)
            {
                CandidateSelector candidates = removeCandidate(r, c);
                if (candidates.isEmpty())
                {
                    m_candidateMap.remove(r);
                    if (!Util.isOptional(r))
                    {
                        PopulateResult result = m_populateResultCache.get(r.getResource());
                        if (result != null)
                        {
                            result.success = false;
                            result.error =
                                    new MissingRequirementError(r, m_populateResultCache.get(c.getResource()).error);
                        }
                        unresolvedResources.add(r.getResource());
                    }
                }
            }
        }
    }

    private CandidateSelector removeCandidate(Requirement req, Capability cap) {
        CandidateSelector candidates = m_candidateMap.get(req);
        candidates.remove(cap);
        return candidates;
    }

    /**
     * Creates a copy of the Candidates object. This is used for creating
     * permutations when package space conflicts are discovered.
     *
     * @return copy of this Candidates object.
     */
    public Candidates copy()
    {
        return new Candidates(
                m_session,
                m_candidateSelectorsUnmodifiable,
                m_dependentMap,
                m_candidateMap.deepClone(),
                m_allWrappedHosts,
                m_populateResultCache,
                m_subtitutableMap,
                m_delta.deepClone());
    }

    public void dump(ResolveContext rc)
    {
        // Create set of all revisions from requirements.
        Set<Resource> resources = new CopyOnWriteSet<Resource>();
        for (Entry<Requirement, CandidateSelector> entry
            : m_candidateMap.entrySet())
        {
            resources.add(entry.getKey().getResource());
        }
        // Now dump the revisions.
        System.out.println("=== BEGIN CANDIDATE MAP ===");
        for (Resource resource : resources)
        {
            Wiring wiring = rc.getWirings().get(resource);
            System.out.println("  " + resource
                + " (" + ((wiring != null) ? "RESOLVED)" : "UNRESOLVED)"));
            List<Requirement> reqs = (wiring != null)
                ? wiring.getResourceRequirements(null)
                : resource.getRequirements(null);
            for (Requirement req : reqs)
            {
                CandidateSelector candidates = m_candidateMap.get(req);
                if ((candidates != null) && (!candidates.isEmpty()))
                {
                    System.out.println("    " + req + ": " + candidates);
                }
            }
            reqs = (wiring != null)
                ? Util.getDynamicRequirements(wiring.getResourceRequirements(null))
                : Util.getDynamicRequirements(resource.getRequirements(null));
            for (Requirement req : reqs)
            {
                CandidateSelector candidates = m_candidateMap.get(req);
                if ((candidates != null) && (!candidates.isEmpty()))
                {
                    System.out.println("    " + req + ": " + candidates);
                }
            }
        }
        System.out.println("=== END CANDIDATE MAP ===");
    }

    public Candidates permutate(Requirement req)
    {
        if (!Util.isMultiple(req) && canRemoveCandidate(req))
        {
            Candidates perm = copy();
            perm.removeFirstCandidate(req);
            return perm;
        }
        return null;
    }

    public boolean canRemoveCandidate(Requirement req)
    {
        CandidateSelector candidates = m_candidateMap.get(req);
        if (candidates != null)
        {
            Capability current = candidates.getCurrentCandidate();
            if (current != null)
            {
                // IMPLEMENTATION NOTE:
                // Here we check for a req that is used for a substitutable export.
                // If we find a substitutable req then an extra check is done to see
                // if the substitutable capability is currently depended on as the
                // only provider of some other requirement.  If it is then we do not
                // allow the candidate to be removed.
                // This is done because of the way we attempt to reduce permutations
                // checked by permuting all used requirements that conflict with a
                // directly imported/required capability in one go.
                // If we allowed these types of substitutable requirements to move
                // to the next capability then the permutation would be thrown out
                // because it would cause some other resource to not resolve.
                // That in turn would throw out the complete permutation along with
                // any follow on permutations that could have resulted.
                // See ResolverImpl::checkPackageSpaceConsistency

                // Check if the current candidate is substitutable by the req;
                // This check is necessary here because of the way we traverse used blames
                // allows multiple requirements to be permuted in one Candidates
                if (req.equals(m_subtitutableMap.get(current)))
                {
                    // this is a substitute req,
                    // make sure there is not an existing dependency that would fail if we substitute
                    Set<Requirement> dependents = m_dependentMap.get(current);
                    if (dependents != null)
                    {
                        for (Requirement dependent : dependents)
                        {
                            CandidateSelector dependentSelector = m_candidateMap.get(
                                    dependent);
                            // If the dependent selector only has one capability left then check if
                            // the current candidate is the selector's current candidate.
                            if (dependentSelector != null
                                    && dependentSelector.getRemainingCandidateCount() <= 1)
                            {
                                if (current.equals(
                                        dependentSelector.getCurrentCandidate()))
                                {
                                    // return false since we do not want to allow this requirement
                                    // to substitute the capability
                                    return false;
                                }
                            }
                        }
                    }
                }
            }
            return candidates.getRemainingCandidateCount() > 1 || Util.isOptional(req);
        }
        return false;
    }

    static class DynamicImportFailed extends ResolutionError {

        private final Requirement requirement;

        public DynamicImportFailed(Requirement requirement) {
            this.requirement = requirement;
        }

        public String getMessage() {
            return "Dynamic import failed.";
        }

        public Collection<Requirement> getUnresolvedRequirements() {
            return Collections.singleton(requirement);
        }

        @Override
        public ResolutionException toException() {
            return new ReasonException(ReasonException.Reason.DynamicImport, getMessage(), null, getUnresolvedRequirements());
        }

    }

    static class FragmentNotSelectedError extends ResolutionError {

        private final Resource resource;

        public FragmentNotSelectedError(Resource resource) {
            this.resource = resource;
        }

        public String getMessage() {
            return "Fragment was not selected for attachment: " + resource;
        }

        @Override
        public Collection<Requirement> getUnresolvedRequirements() {
            return resource.getRequirements(HostNamespace.HOST_NAMESPACE);
        }

        @Override
        public ResolutionException toException() {
            return new ReasonException(ReasonException.Reason.FragmentNotSelected, getMessage(), null, getUnresolvedRequirements());
        }

    }

    static class MissingRequirementError extends ResolutionError {

        private final Requirement requirement;
        private final ResolutionError cause;

        public MissingRequirementError(Requirement requirement) {
            this(requirement, null);
        }

        public MissingRequirementError(Requirement requirement, ResolutionError cause) {
            this.requirement = requirement;
            this.cause = cause;
        }

        public String getMessage() {
            String msg = "Unable to resolve " + requirement.getResource()
                    + ": missing requirement " + requirement;
            if (cause != null)
            {
                msg = msg + " [caused by: " + cause.getMessage() + "]";
            }
            return msg;
        }

        public Collection<Requirement> getUnresolvedRequirements() {
            return Collections.singleton(requirement);
        }

        @Override
        public ResolutionException toException() {
            return new ReasonException(
                ReasonException.Reason.MissingRequirement, getMessage(), cause != null ? cause.toException() : null, getUnresolvedRequirements());
        }

    }

}
