Set<String> getRecursiveDependencies(Set<String> missingDependencies,
      Map<String, List<String>> dependencies, Set<String> servicesInUpgrade,
      Set<String> installedServices) {
    Set<String> results = Sets.newHashSet();
    results.addAll(missingDependencies);

    for (String missingDependency : missingDependencies) {
      if (dependencies.containsKey(missingDependency)) {
        List<String> subDependencies = dependencies.get(missingDependency);
        for (String subDependency : subDependencies) {
          if (!missingDependencies.contains(subDependency)
              && installedServices.contains(subDependency)
              && !servicesInUpgrade.contains(subDependency)) {
            results.add(subDependency);
            results.addAll(getRecursiveDependencies(results, dependencies, servicesInUpgrade,
                installedServices));
          }
        }
      }
    }

    return results;
  }
Gets all dependencies required to perform an upgrade, considering that the
original set's depenencies may have dependencies of their own.

@param missingDependencies
         the set of missing dependencies so far.
@param dependencies
         the master list of dependency associations
@param servicesInUpgrade
         the services which the VDF indicates are going to be in the
         upgrade *
@param installedServices
         the services installed in the cluster
@return a new set including any dependencies of those which were already
        found
ambari-server/src/main/java/org/apache/ambari/server/state/repository/VersionDefinitionXml.java