private boolean resolveConflict()

in src/java/org/apache/ivy/core/resolve/ResolveEngine.java [869:1026]


    private boolean resolveConflict(VisitNode node, VisitNode ancestor, String conf,
            Collection<IvyNode> toevict) {
        if (ancestor == null || node == ancestor) {
            return true;
        }
        // check if job is not already done
        if (checkConflictSolvedEvicted(node, ancestor)) {
            // job is done and node is evicted, nothing to do
            return true;
        }
        boolean debugConflictResolution = settings.debugConflictResolution();
        if (checkConflictSolvedSelected(node, ancestor)) {
            // job is done and node is selected, nothing to do for this ancestor, but we still have
            // to check higher levels, for which conflict resolution might have been impossible
            // before
            if (resolveConflict(node, ancestor.getParent(), conf, toevict)) {
                // now that conflict resolution is ok in ancestors
                // we just have to check if the node wasn't previously evicted in root ancestor
                EvictionData evictionData = node.getEvictionDataInRoot(node.getRootModuleConf(),
                    ancestor);
                if (evictionData != null) {
                    // node has been previously evicted in an ancestor: we mark it as evicted
                    if (debugConflictResolution) {
                        Message.debug(node + " was previously evicted in root module conf "
                                + node.getRootModuleConf());
                    }
                    node.markEvicted(evictionData);
                    if (debugConflictResolution) {
                        Message.debug("evicting " + node + " by " + evictionData);
                    }
                }
                return true;
            } else {
                return false;
            }
        }

        // compute conflicts
        Set<IvyNode> resolvedNodes = ancestor.getNode().getResolvedNodes(node.getModuleId(),
            node.getRootModuleConf());
        resolvedNodes.addAll(ancestor.getNode().getPendingConflicts(node.getRootModuleConf(),
            node.getModuleId()));
        Collection<IvyNode> conflicts = computeConflicts(node, ancestor, conf, toevict,
            resolvedNodes);

        ConflictManager conflictManager = null;
        for (VisitNode current : ancestor.getPath()) {
            ModuleDescriptor descriptor = current.getNode().getDescriptor();
            if (descriptor == null) {
                throw new IllegalStateException(
                        "impossible to get conflict manager when data has not been loaded. IvyNode = "
                                + current.getNode());
            }

            conflictManager = descriptor.getConflictManager(node.getModuleId());
            if (conflictManager != null) {
                break;
            }
        }

        if (conflictManager == null) {
            conflictManager = settings.getConflictManager(node.getModuleId());
        }

        Collection<IvyNode> resolved = resolveConflicts(node, ancestor, conflicts, conflictManager);

        if (resolved == null) {
            if (debugConflictResolution) {
                Message.debug("impossible to resolve conflicts for " + node + " in " + ancestor
                        + " yet");
                Message.debug("setting all nodes as pending conflicts for later conflict"
                        + " resolution: " + conflicts);
            }
            ancestor.getNode().setPendingConflicts(node.getModuleId(), node.getRootModuleConf(),
                conflicts);
            return false;
        }

        if (debugConflictResolution) {
            Message.debug("selected revisions for " + node + " in " + ancestor + ": " + resolved);
        }
        if (resolved.contains(node.getNode())) {
            // node has been selected for the current parent

            // handle previously selected nodes that are now evicted by this new node
            toevict = resolvedNodes;
            toevict.removeAll(resolved);

            for (IvyNode te : toevict) {
                te.markEvicted(node.getRootModuleConf(), ancestor.getNode(), conflictManager,
                    resolved);

                if (debugConflictResolution) {
                    Message.debug("evicting " + te + " by "
                            + te.getEvictedData(node.getRootModuleConf()));
                }
            }

            // it's very important to update resolved and evicted nodes BEFORE recompute parent call
            // to allow it to recompute its resolved collection with correct data
            // if necessary
            ancestor.getNode().setResolvedNodes(node.getModuleId(), node.getRootModuleConf(),
                resolved);

            Collection<IvyNode> evicted = new HashSet<>(ancestor.getNode().getEvictedNodes(
                    node.getModuleId(), node.getRootModuleConf()));
            evicted.removeAll(resolved);
            evicted.addAll(toevict);
            ancestor.getNode().setEvictedNodes(node.getModuleId(), node.getRootModuleConf(),
                evicted);
            ancestor.getNode().setPendingConflicts(node.getModuleId(), node.getRootModuleConf(),
                Collections.<IvyNode> emptySet());

            return resolveConflict(node, ancestor.getParent(), conf, toevict);
        } else {
            // node has been evicted for the current parent
            if (resolved.isEmpty()) {
                if (debugConflictResolution) {
                    Message.verbose("conflict manager '" + conflictManager
                            + "' evicted all revisions among " + conflicts);
                }
            }

            // it's time to update parent resolved and evicted with what was found

            Collection<IvyNode> evicted = new HashSet<>(ancestor.getNode().getEvictedNodes(
                    node.getModuleId(), node.getRootModuleConf()));
            toevict.removeAll(resolved);
            evicted.removeAll(resolved);
            evicted.addAll(toevict);
            evicted.add(node.getNode());
            ancestor.getNode().setEvictedNodes(node.getModuleId(), node.getRootModuleConf(),
                evicted);
            ancestor.getNode().setPendingConflicts(node.getModuleId(), node.getRootModuleConf(),
                Collections.<IvyNode> emptySet());

            node.markEvicted(ancestor, conflictManager, resolved);
            if (debugConflictResolution) {
                Message.debug("evicting " + node + " by " + node.getEvictedData());
            }

            // if resolved changed we have to go up in the graph
            Collection<IvyNode> prevResolved = ancestor.getNode().getResolvedNodes(
                node.getModuleId(), node.getRootModuleConf());
            boolean solved = true;
            if (!prevResolved.equals(resolved)) {
                ancestor.getNode().setResolvedNodes(node.getModuleId(), node.getRootModuleConf(),
                    resolved);
                for (IvyNode sel : resolved) {
                    if (!prevResolved.contains(sel)) {
                        solved &= resolveConflict(node.gotoNode(sel), ancestor.getParent(), conf,
                            toevict);
                    }
                }
            }
            return solved;
        }
    }