using Raven.Client.Documents; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Threading.Tasks; using zero.Core.Entities; namespace zero.Core.Routing { public class PageRouteResolverHelper { protected ConcurrentDictionary> PageRouteCache { get; set; } = new(); public async Task ResolveFor(RoutingContext context, Func predicate = null) { return (await ResolveAllFor(context, predicate)).FirstOrDefault(); } public async Task ResolvePageFor(RoutingContext context, Func predicate = null) { return (await ResolveAllPagesFor(context, predicate)).FirstOrDefault(); } public async Task> ResolveAllFor(RoutingContext context, Func predicate = null) { string fullKey = typeof(T).Name.ToString().ToLower() + ":" + context.Context.AppId; if (!PageRouteCache.TryGetValue(fullKey, out HashSet<(Page, Route)> routes)) { List pages = new(); IEnumerable>> resolvers = context.Context.Options.Routing.PageResolvers.GetAll(typeof(T)); foreach (Expression> resolver in resolvers.Reverse()) { pages.AddRange(await context.Session.Query().Where(resolver).ToListAsync()); } Dictionary idToPage = pages.ToDictionary(x => context.Context.Options.Routing.PageRouteIdBuilder.Generate(x), x => x); Dictionary idToRoute = await context.Session.LoadAsync(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> ResolveAllPagesFor(RoutingContext context, Func predicate = null) { string fullKey = typeof(T).Name.ToString().ToLower() + ":" + context.Context.AppId; if (!PageRouteCache.TryGetValue(fullKey, out HashSet<(Page, Route)> routes)) { List pages = new(); IEnumerable>> resolvers = context.Context.Options.Routing.PageResolvers.GetAll(typeof(T)); foreach (Expression> resolver in resolvers.Reverse()) { pages.AddRange(await context.Session.Query().Where(resolver).ToListAsync()); } Dictionary idToPage = pages.ToDictionary(x => context.Context.Options.Routing.PageRouteIdBuilder.Generate(x), x => x); Dictionary idToRoute = await context.Session.LoadAsync(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(); } } }