JD2022-TU1/main/tools/framework/JD.Collections/Utilities/GraphWalker.cs

60 lines
1.7 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using JD.Kernel.StaticHelpers;
namespace JD.Collections.Utilities
{
public abstract class GraphWalker<T>
{
#region Methods
protected abstract IEnumerable<T> GetDependenciesOf(T item);
public bool CanReach(T source, T target)
{
Throw.IfNull(source, "source");
Throw.IfNull(target, "target");
Set<T> reachable = new Set<T>();
Predicate<T> isTarget = targetToTest => Equals(target, targetToTest);
return CanReach(source, isTarget, reachable);
}
public bool CanReach(T source, Predicate<T> target)
{
Throw.IfNull(source, "source");
Throw.IfNull(target, "target");
Set<T> reachable = new Set<T>();
return CanReach(source, target, reachable);
}
private bool CanReach(T source, Predicate<T> isTarget, Set<T> reachable)
{
if (isTarget(source))
{
return true;
}
if (reachable.Add(source))
{
return GetDependenciesOf(source).Any(dependency => CanReach(dependency, isTarget, reachable));
}
return false;
}
/// <summary>
/// True if the source can reach the target in one step.
/// </summary>
public bool IsAdjacent(T source, Predicate<T> isTrarget)
{
// It could have used a Func<T, bool> directly but I prefer the predicate (they are more explicit).
return GetDependenciesOf(source).Any(dependency => isTrarget(dependency));
}
#endregion
}
}