private Set<ResolvedArtifact> getArtifacts(ConfigurationNode childConfiguration) {
   String[] targetConfigurations =
       from.metaData.getHierarchy().toArray(new String[from.metaData.getHierarchy().size()]);
   DependencyArtifactDescriptor[] dependencyArtifacts =
       dependencyDescriptor.getDependencyArtifacts(targetConfigurations);
   if (dependencyArtifacts.length == 0) {
     return Collections.emptySet();
   }
   Set<ResolvedArtifact> artifacts = new LinkedHashSet<ResolvedArtifact>();
   for (DependencyArtifactDescriptor artifactDescriptor : dependencyArtifacts) {
     ModuleRevisionId id =
         childConfiguration.moduleRevision.metaData.getDescriptor().getModuleRevisionId();
     Artifact artifact =
         new DefaultArtifact(
             id,
             null,
             artifactDescriptor.getName(),
             artifactDescriptor.getType(),
             artifactDescriptor.getExt(),
             artifactDescriptor.getUrl(),
             artifactDescriptor.getQualifiedExtraAttributes());
     artifacts.add(
         resolveState.builder.newArtifact(
             childConfiguration.getResult(),
             artifact,
             targetModuleRevision.resolve().getArtifactResolver()));
   }
   return artifacts;
 }
    public void visitOutgoingDependencies(Collection<DependencyEdge> target) {
      // If this configuration's version is in conflict, don't do anything
      // If not traversed before, add all selected outgoing edges
      // If traversed before, and the selected modules have changed, remove previous outgoing edges
      // and add outgoing edges again with
      //    the new selections.
      // If traversed before, and the selected modules have not changed, ignore
      // If none of the incoming edges are transitive, then the node has no outgoing edges

      if (moduleRevision.state != ModuleState.Selected) {
        LOGGER.debug("version for {} is not selected. ignoring.", this);
        return;
      }

      List<DependencyEdge> transitiveIncoming = new ArrayList<DependencyEdge>();
      for (DependencyEdge edge : incomingEdges) {
        if (edge.isTransitive()) {
          transitiveIncoming.add(edge);
        }
      }

      if (transitiveIncoming.isEmpty() && this != resolveState.root) {
        if (previousTraversal != null) {
          removeOutgoingEdges();
        }
        if (incomingEdges.isEmpty()) {
          LOGGER.debug("{} has no incoming edges. ignoring.", this);
        } else {
          LOGGER.debug("{} has no transitive incoming edges. ignoring outgoing edges.", this);
        }
        return;
      }

      ModuleVersionSpec selectorSpec = getSelector(transitiveIncoming);
      if (previousTraversal != null) {
        if (previousTraversal.acceptsSameModulesAs(selectorSpec)) {
          LOGGER.debug(
              "Changed edges for {} selects same versions as previous traversal. ignoring", this);
          return;
        }
        removeOutgoingEdges();
      }

      for (DependencyMetaData dependency : metaData.getDependencies()) {
        DependencyDescriptor dependencyDescriptor = dependency.getDescriptor();
        ModuleId targetModuleId = dependencyDescriptor.getDependencyRevisionId().getModuleId();
        if (!selectorSpec.isSatisfiedBy(targetModuleId)) {
          LOGGER.debug("{} is excluded from {}.", targetModuleId, this);
          continue;
        }
        DependencyEdge dependencyEdge =
            new DependencyEdge(this, dependency, selectorSpec, resolveState);
        outgoingEdges.add(dependencyEdge);
        target.add(dependencyEdge);
      }
      previousTraversal = selectorSpec;
    }
 public void removeOutgoingEdges() {
   for (DependencyEdge outgoingDependency : outgoingEdges) {
     outgoingDependency.removeFromTargetConfigurations();
   }
   outgoingEdges.clear();
   previousTraversal = null;
 }
 /**
  * Called when a change is made to a configuration node, such that its dependency graph
  * <em>may</em> now be larger than it previously was, and the node should be visited.
  */
 public void onMoreSelected(ConfigurationNode configuration) {
   // Add to the end of the queue, so that we traverse the graph in breadth-wise order to pick up
   // as many conflicts as
   // possible before attempting to resolve them
   if (queued.add(configuration)) {
     queue.addLast(configuration);
   }
 }
    public void attachToParents(
        ConfigurationNode childConfiguration, ResolvedConfigurationBuilder result) {
      ResolvedConfigurationIdentifier parent = from.getResult();
      ResolvedConfigurationIdentifier child = childConfiguration.getResult();
      result.addChild(parent, child);

      Set<ResolvedArtifact> artifacts = getArtifacts(childConfiguration);
      if (artifacts.isEmpty()) {
        artifacts = childConfiguration.getArtifacts();
      }
      // TODO SF merge with addChild
      result.addParentSpecificArtifacts(child, parent, artifacts);

      if (parent == resolveState.root.getResult()) {
        EnhancedDependencyDescriptor enhancedDependencyDescriptor =
            (EnhancedDependencyDescriptor) dependencyDescriptor;
        result.addFirstLevelDependency(enhancedDependencyDescriptor.getModuleDependency(), child);
      }
    }
 public void restart(ModuleVersionResolveState selected) {
   select(selected);
   for (ModuleVersionResolveState version : versions.values()) {
     version.restart(selected);
   }
   for (DependencyEdge dependency : new ArrayList<DependencyEdge>(unattachedDependencies)) {
     dependency.restart(selected);
   }
   unattachedDependencies.clear();
 }
 public Set<ResolvedArtifact> getArtifacts() {
   if (artifacts == null) {
     artifacts = new LinkedHashSet<ResolvedArtifact>();
     for (Artifact artifact : metaData.getArtifacts()) {
       artifacts.add(
           resolveState.builder.newArtifact(
               getResult(), artifact, moduleRevision.resolve().getArtifactResolver()));
     }
   }
   return artifacts;
 }
 public void attachToTargetConfigurations() {
   if (targetModuleRevision.state != ModuleState.Selected) {
     return;
   }
   calculateTargetConfigurations();
   for (ConfigurationNode targetConfiguration : targetConfigurations) {
     targetConfiguration.addIncomingEdge(this);
   }
   if (!targetConfigurations.isEmpty()) {
     selector.getSelectedModule().removeUnattachedDependency(this);
   }
 }
 public void restart(ModuleVersionResolveState selected) {
   // Restarting this configuration after conflict resolution.
   // If this configuration belongs to the select version, queue ourselves up for traversal.
   // If not, then move our incoming edges across to the selected configuration
   if (moduleRevision == selected) {
     resolveState.onMoreSelected(this);
   } else {
     for (DependencyEdge dependency : incomingEdges) {
       dependency.restart(selected);
     }
     incomingEdges.clear();
   }
 }
    private void calculateTargetConfigurations() {
      targetConfigurations.clear();
      ModuleVersionMetaData targetModuleVersion = targetModuleRevision.getMetaData();
      if (targetModuleVersion == null) {
        // Broken version
        return;
      }

      Set<ConfigurationMetaData> targetConfigurations =
          resolveState.dependencyToConfigurationResolver.resolveTargetConfigurations(
              dependencyMetaData, from.metaData, targetModuleVersion);
      for (ConfigurationMetaData targetConfiguration : targetConfigurations) {
        ConfigurationNode targetConfigurationNode =
            resolveState.getConfigurationNode(targetModuleRevision, targetConfiguration.getName());
        this.targetConfigurations.add(targetConfigurationNode);
      }
    }
  /**
   * Traverses the dependency graph, resolving conflicts and building the paths from the root
   * configuration.
   */
  private void traverseGraph(ResolveState resolveState) {
    Set<ModuleIdentifier> conflicts = new LinkedHashSet<ModuleIdentifier>();

    resolveState.onMoreSelected(resolveState.root);

    List<DependencyEdge> dependencies = new ArrayList<DependencyEdge>();
    while (resolveState.peek() != null || !conflicts.isEmpty()) {
      if (resolveState.peek() != null) {
        ConfigurationNode node = resolveState.pop();
        LOGGER.debug("Visiting configuration {}.", node);

        // Calculate the outgoing edges of this configuration
        dependencies.clear();
        node.visitOutgoingDependencies(dependencies);

        for (DependencyEdge dependency : dependencies) {
          LOGGER.debug("Visiting dependency {}", dependency);

          // Resolve dependency to a particular revision
          ModuleVersionResolveState moduleRevision = dependency.resolveModuleRevisionId();
          if (moduleRevision == null) {
            // Failed to resolve.
            continue;
          }
          ModuleIdentifier moduleId = moduleRevision.id.getModule();

          // Check for a new conflict
          if (moduleRevision.state == ModuleState.New) {
            ModuleResolveState module = resolveState.getModule(moduleId);

            // A new module revision. Check for conflict
            Collection<ModuleVersionResolveState> versions = module.getVersions();
            if (versions.size() == 1) {
              // First version of this module. Select it for now
              LOGGER.debug("Selecting new module version {}", moduleRevision);
              module.select(moduleRevision);
            } else {
              // Not the first version of this module. We have a new conflict
              LOGGER.debug("Found new conflicting module version {}", moduleRevision);
              conflicts.add(moduleId);

              // Deselect the currently selected version, and remove all outgoing edges from the
              // version
              // This will propagate through the graph and prune configurations that are no longer
              // required
              ModuleVersionResolveState previouslySelected = module.clearSelection();
              if (previouslySelected != null) {
                for (ConfigurationNode configuration : previouslySelected.configurations) {
                  configuration.removeOutgoingEdges();
                }
              }
            }
          }

          dependency.attachToTargetConfigurations();
        }
      } else {
        // We have some batched up conflicts. Resolve the first, and continue traversing the graph
        ModuleIdentifier moduleId = conflicts.iterator().next();
        conflicts.remove(moduleId);
        ModuleResolveState module = resolveState.getModule(moduleId);
        ModuleVersionResolveState selected =
            conflictResolver.select(module.getVersions(), resolveState.root.moduleRevision);
        LOGGER.debug("Selected {} from conflicting modules {}.", selected, module.getVersions());

        // Restart each configuration. For the evicted configuration, this means moving incoming
        // dependencies across to the
        // matching selected configuration. For the select configuration, this mean traversing its
        // dependencies.
        module.restart(selected);
      }
    }
  }
 public void removeIncomingEdge(DependencyEdge dependencyEdge) {
   incomingEdges.remove(dependencyEdge);
   resolveState.onFewerSelected(this);
 }
 public void addIncomingEdge(DependencyEdge dependencyEdge) {
   incomingEdges.add(dependencyEdge);
   resolveState.onMoreSelected(this);
 }
 public void removeFromTargetConfigurations() {
   for (ConfigurationNode targetConfiguration : targetConfigurations) {
     targetConfiguration.removeIncomingEdge(this);
   }
   targetConfigurations.clear();
 }
 public void addConfiguration(ConfigurationNode configurationNode) {
   configurations.add(configurationNode);
 }
 public void removeUnattachedDependency(DependencyEdge edge) {
   unattachedDependencies.remove(edge);
 }
 public ConfigurationNode pop() {
   ConfigurationNode next = queue.removeFirst();
   queued.remove(next);
   return next;
 }
 /**
  * Called when a change is made to a configuration node, such that its dependency graph
  * <em>may</em> now be smaller than it previously was, and the node should be visited.
  */
 public void onFewerSelected(ConfigurationNode configuration) {
   // Add to the front of the queue, to flush out configurations that are no longer required.
   if (queued.add(configuration)) {
     queue.addFirst(configuration);
   }
 }
 public void addUnattachedDependency(DependencyEdge edge) {
   unattachedDependencies.add(edge);
 }
    private Collection<List<ModuleVersionIdentifier>> calculatePaths(
        BrokenDependency brokenDependency) {
      // Include the shortest path from each version that has a direct dependency on the broken
      // dependency, back to the root

      Map<ModuleVersionResolveState, List<ModuleVersionIdentifier>> shortestPaths =
          new LinkedHashMap<ModuleVersionResolveState, List<ModuleVersionIdentifier>>();
      List<ModuleVersionIdentifier> rootPath = new ArrayList<ModuleVersionIdentifier>();
      rootPath.add(root.moduleRevision.id);
      shortestPaths.put(root.moduleRevision, rootPath);

      Set<ModuleVersionResolveState> directDependees =
          new LinkedHashSet<ModuleVersionResolveState>();
      for (ConfigurationNode node : brokenDependency.requiredBy) {
        directDependees.add(node.moduleRevision);
      }

      Set<ModuleVersionResolveState> seen = new HashSet<ModuleVersionResolveState>();
      LinkedList<ModuleVersionResolveState> queue = new LinkedList<ModuleVersionResolveState>();
      queue.addAll(directDependees);
      while (!queue.isEmpty()) {
        ModuleVersionResolveState version = queue.getFirst();
        if (version == root.moduleRevision) {
          queue.removeFirst();
        } else if (seen.add(version)) {
          for (ConfigurationNode configuration : version.configurations) {
            for (DependencyEdge dependencyEdge : configuration.incomingEdges) {
              queue.add(0, dependencyEdge.from.moduleRevision);
            }
          }
        } else {
          queue.remove();
          List<ModuleVersionIdentifier> shortest = null;
          for (ConfigurationNode configuration : version.configurations) {
            for (DependencyEdge dependencyEdge : configuration.incomingEdges) {
              List<ModuleVersionIdentifier> candidate =
                  shortestPaths.get(dependencyEdge.from.moduleRevision);
              if (candidate == null) {
                continue;
              }
              if (shortest == null) {
                shortest = candidate;
              } else if (shortest.size() > candidate.size()) {
                shortest = candidate;
              }
            }
          }
          if (shortest == null) {
            continue;
          }
          List<ModuleVersionIdentifier> path = new ArrayList<ModuleVersionIdentifier>();
          path.addAll(shortest);
          path.add(version.id);
          shortestPaths.put(version, path);
        }
      }

      List<List<ModuleVersionIdentifier>> paths = new ArrayList<List<ModuleVersionIdentifier>>();
      for (ModuleVersionResolveState version : directDependees) {
        List<ModuleVersionIdentifier> path = shortestPaths.get(version);
        paths.add(path);
      }
      return paths;
    }