All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.molgenis.data.util.GenericDependencyResolver Maven / Gradle / Ivy

There is a newer version: 8.4.5
Show newest version
package org.molgenis.data.util;

import static com.google.common.collect.ImmutableSet.copyOf;
import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Sets.difference;
import static com.google.common.collect.Sets.newHashSet;
import static java.util.Collections.singleton;
import static java.util.stream.Collectors.toSet;

import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import org.molgenis.data.MolgenisDataException;
import org.springframework.stereotype.Component;

@Component
public class GenericDependencyResolver {
  public  List resolve(Collection items, Function> getDependencies) {
    List result = newArrayList();
    Set alreadyResolved = newHashSet();
    Set stillToResolve = newHashSet(items);

    while (!stillToResolve.isEmpty()) {
      List newlyResolved =
          stillToResolve.stream()
              .filter(item -> alreadyResolved.containsAll(getDependencies.apply(item)))
              .collect(Collectors.toList());
      if (newlyResolved.isEmpty()) {
        throw new MolgenisDataException(
            "Could not resolve dependencies of items "
                + stillToResolve
                + ". Are there circular dependencies?");
      }
      alreadyResolved.addAll(newlyResolved);
      stillToResolve.removeAll(newlyResolved);
      result.addAll(newlyResolved);
    }
    return result;
  }

  /**
   * Retrieves all items that depend on a given item.
   *
   * @param item the item that the other items depend on
   * @param getDepth function that returns the depth up to which a specific item's dependencies are
   *     resolved
   * @param getDependants function that returns the items that depend on a specific item
   * @param  the type of the item
   * @return Set of items that directly or indirectly depend on the given item
   */
  public  Set getAllDependants(
      A item, Function getDepth, Function> getDependants) {
    Set currentGeneration = singleton(item);
    Set result = newHashSet();
    Set visited = newHashSet();

    for (int depth = 0; !currentGeneration.isEmpty(); depth++) {
      currentGeneration =
          copyOf(difference(getDirectDependants(currentGeneration, getDependants), visited));
      result.addAll(
          currentGeneration.stream().filter(getDepthFilter(depth, getDepth)).collect(toSet()));
      visited.addAll(currentGeneration);
    }

    return result;
  }

  private  Set getDirectDependants(Set items, Function> getDependants) {
    return items.stream().flatMap(item -> getDependants.apply(item).stream()).collect(toSet());
  }

  private  Predicate getDepthFilter(int depth, Function getDepth) {
    return item -> getDepth.apply(item) > depth;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy