Files
mixtape/zero.Core/Routing/PageRouteProvider/PageRouteResolverHelper.cs
T

182 lines
5.8 KiB
C#
Raw Normal View History

2021-11-20 13:52:28 +01:00
using Raven.Client.Documents;
using Raven.Client.Documents.Linq;
using System.Collections.Concurrent;
using System.Linq.Expressions;
namespace zero.Routing;
public class PageRouteResolverHelper
{
protected ConcurrentDictionary<string, HashSet<(Page, Route)>> PageRouteCache { get; set; } = new();
public async Task<Route> ResolveFor<T>(RoutingContext context, Func<Page, bool> predicate = null)
{
return (await ResolveAllFor<T>(context, predicate)).FirstOrDefault();
}
public async Task<Page> ResolvePageFor<T>(RoutingContext context, Func<Page, bool> predicate = null)
{
return (await ResolveAllPagesFor<T>(context, predicate)).FirstOrDefault();
}
public async Task<HashSet<Route>> ResolveAllFor<T>(RoutingContext context, Func<Page, bool> predicate = null)
{
2021-11-26 12:31:33 +01:00
RoutingOptions options = context.Context.Options.For<RoutingOptions>();
2021-11-20 13:52:28 +01:00
string fullKey = typeof(T).Name.ToString().ToLower() + ":" + context.Context.AppId;
if (!PageRouteCache.TryGetValue(fullKey, out HashSet<(Page, Route)> routes))
{
List<Page> pages = new();
2021-11-26 12:31:33 +01:00
IEnumerable<Expression<Func<Page, bool>>> resolvers = options.PageResolvers.GetAll(typeof(T));
2021-11-20 13:52:28 +01:00
foreach (Expression<Func<Page, bool>> resolver in resolvers.Reverse())
{
pages.AddRange(await context.Session.Query<Page>().Where(resolver).ToListAsync());
}
2021-11-26 12:31:33 +01:00
Dictionary<string, Page> idToPage = pages.ToDictionary(x => options.PageRouteIdBuilder.Generate(x), x => x);
2021-11-20 13:52:28 +01:00
Dictionary<string, Route> idToRoute = await context.Session.LoadAsync<Route>(idToPage.Select(x => x.Key));
routes = new();
foreach ((string id, Page page) in idToPage)
{
if (idToRoute.TryGetValue(id, out Route route) && route != null)
{
routes.Add((page, route));
}
}
PageRouteCache.TryAdd(fullKey, routes);
}
if (predicate != null)
{
return routes.Where(x => predicate(x.Item1)).Select(x => x.Item2).ToHashSet();
}
return routes.Select(x => x.Item2).ToHashSet();
}
public async Task<HashSet<Page>> ResolveAllPagesFor<T>(RoutingContext context, Func<Page, bool> predicate = null)
{
2021-11-26 12:31:33 +01:00
RoutingOptions options = context.Context.Options.For<RoutingOptions>();
2021-11-20 13:52:28 +01:00
string fullKey = typeof(T).Name.ToString().ToLower() + ":" + context.Context.AppId;
if (!PageRouteCache.TryGetValue(fullKey, out HashSet<(Page, Route)> routes))
{
List<Page> pages = new();
2021-11-26 12:31:33 +01:00
IEnumerable<Expression<Func<Page, bool>>> resolvers = options.PageResolvers.GetAll(typeof(T));
2021-11-20 13:52:28 +01:00
foreach (Expression<Func<Page, bool>> resolver in resolvers.Reverse())
{
pages.AddRange(await context.Session.Query<Page>().Where(resolver).ToListAsync());
}
2021-11-26 12:31:33 +01:00
Dictionary<string, Page> idToPage = pages.ToDictionary(x => options.PageRouteIdBuilder.Generate(x), x => x);
2021-11-20 13:52:28 +01:00
Dictionary<string, Route> idToRoute = await context.Session.LoadAsync<Route>(idToPage.Select(x => x.Key));
routes = new();
foreach ((string id, Page page) in idToPage)
{
if (idToRoute.TryGetValue(id, out Route route) && route != null)
{
routes.Add((page, route));
}
}
PageRouteCache.TryAdd(fullKey, routes);
}
if (predicate != null)
{
return routes.Where(x => predicate(x.Item1)).Select(x => x.Item1).ToHashSet();
}
return routes.Select(x => x.Item1).ToHashSet();
}
public async Task<Dictionary<Page, Route>> ResolveAllForAsDictionary<T>(RoutingContext context, Func<(Page, Route), bool> predicate = null)
{
2021-11-26 12:31:33 +01:00
RoutingOptions options = context.Context.Options.For<RoutingOptions>();
2021-11-20 13:52:28 +01:00
string fullKey = typeof(T).Name.ToString().ToLower() + ":" + context.Context.AppId;
if (!PageRouteCache.TryGetValue(fullKey, out HashSet<(Page, Route)> routes))
{
List<Page> pages = new();
2021-11-26 12:31:33 +01:00
IEnumerable<Expression<Func<Page, bool>>> resolvers = options.PageResolvers.GetAll(typeof(T));
2021-11-20 13:52:28 +01:00
foreach (Expression<Func<Page, bool>> resolver in resolvers.Reverse())
{
pages.AddRange(await context.Session.Query<Page>().Where(resolver).ToListAsync());
}
2021-11-26 12:31:33 +01:00
Dictionary<string, Page> idToPage = pages.ToDictionary(x => options.PageRouteIdBuilder.Generate(x), x => x);
2021-11-20 13:52:28 +01:00
Dictionary<string, Route> idToRoute = await context.Session.LoadAsync<Route>(idToPage.Select(x => x.Key));
routes = new();
foreach ((string id, Page page) in idToPage)
{
if (idToRoute.TryGetValue(id, out Route route) && route != null)
{
routes.Add((page, route));
}
}
PageRouteCache.TryAdd(fullKey, routes);
}
if (predicate != null)
{
return routes.Where(x => predicate(x)).ToDictionary(x => x.Item1, x => x.Item2);
}
return routes.ToDictionary(x => x.Item1, x => x.Item2);
}
public async Task<bool> IsRelevantFor<T>(RoutingContext context, Page page)
{
HashSet<Page> pages = await ResolveAllPagesFor<T>(context);
if (pages.Any(x => x.Id == page.Id))
{
return true;
}
string[] childIds = await GetChildIds(context, page.Id);
return pages.Any(x => childIds.Contains(x.Id));
}
/// <summary>
/// Get relevant pages for a page
/// </summary>
public virtual async Task<List<Page>> GetRelevantPagesFor<T>(RoutingContext context, Page page)
{
HashSet<Page> pages = await ResolveAllPagesFor<T>(context);
string[] childIds = await GetChildIds(context, page.Id);
return pages.Where(x => childIds.Contains(x.Id) || x.Id == page.Id).ToList();
}
/// <summary>
/// Get parents for a page
/// </summary>
protected virtual async Task<string[]> GetChildIds(RoutingContext context, params string[] pageIds)
{
2022-01-06 18:10:58 +01:00
return await context.Session.Query<zero_Pages_ByHierarchy.Result, zero_Pages_ByHierarchy>()
2021-11-20 13:52:28 +01:00
.Where(x => x.PathIds.In(pageIds))
.Select(x => x.Id)
.ToArrayAsync();
}
}