using Microsoft.Extensions.Logging; using Raven.Client.Documents.Linq; namespace zero.Routing; public class Routes : IRoutes { public const char PATH_SEPERATOR = '/'; protected IZeroContext Context { get; set; } protected IZeroStore Store { get; set; } protected ILogger Logger { get; set; } protected IEnumerable Providers { get; set; } public Routes(IZeroContext context, IZeroStore store, ILogger logger, IEnumerable providers) { Context = context; Store = store; Logger = logger; Providers = providers; } /// public async Task GetUrl(T model) where T : ISupportsRouting => (await GetRoute(model))?.Url; /// public async Task GetUrl(string id) where T : ISupportsRouting => (await GetRoute(id))?.Url; /// public async Task> GetUrls(params T[] models) where T : ISupportsRouting => (await GetRoutes(models)).ToDictionary(x => x.Key, x => x.Value?.Url); /// public async Task GetRoute(string id) where T : ISupportsRouting { T model = await GetContext().Session.LoadAsync(id); return await GetRoute(model); } /// public async Task GetRoute(T model) where T : ISupportsRouting { if (model == null) { return null; } if (!TryGetProvider(model, out IRouteProvider routeProvider)) { return null; } RoutingContext context = GetContext(); return await FindRoute(routeProvider, context, model); } /// public async Task> GetRoutes(params T[] models) where T : ISupportsRouting { if (models.Length < 1) { return new(); } T firstExistingModel = models.FirstOrDefault(x => x != null); if (firstExistingModel == null) { return new(); } if (!TryGetProvider(firstExistingModel, out IRouteProvider routeProvider)) { return null; } RoutingContext context = GetContext(); return (await routeProvider.Find(context, models.Select(x => (ISupportsRouting)x).ToArray())).ToDictionary(x => (T)x.Key, x => x.Value); } /// public virtual bool TryGetProvider(T model, out IRouteProvider provider) where T : ISupportsRouting { Type type = model.GetType(); provider = Providers.OrderByDescending(x => x.Priority).FirstOrDefault(x => x.CanHandle(type)); return provider != null; } /// public virtual bool TryGetProvider(string alias, out IRouteProvider provider) { provider = Providers.OrderByDescending(x => x.Priority).FirstOrDefault(x => x.Alias.Equals(alias, StringComparison.InvariantCultureIgnoreCase)); return provider != null; } /// /// Map a route to an MVC endpoint /// //public virtual RouteProviderEndpoint MapEndpoint(IResolvedRoute route) //{ // IEnumerable> resolvers = Options.Routing.EndpointResolvers.GetAll(route.GetType()); // foreach (Func resolver in resolvers.Reverse()) // { // RouteProviderEndpoint endpoint = resolver(route); // if (endpoint != null) // { // return endpoint; // } // } // return Options.Routing.DefaultEndpoint; //} /// /// Find a persisted route for an entity /// protected virtual async Task FindRoute(IRouteProvider provider, RoutingContext context, ISupportsRouting model) { return await provider.Find(context, model); } /// /// Build a new routing context /// protected virtual RoutingContext GetContext() { return new(Store, Context, Store.Session()); } } public interface IRoutes { /// /// Get the URL for an entity /// Task GetUrl(T model) where T : ISupportsRouting; /// /// Get the URL for an entity /// Task GetUrl(string id) where T : ISupportsRouting; /// /// Get URLs for multiple entities /// Task> GetUrls(params T[] models) where T : ISupportsRouting; /// /// Get the route object for an entity /// Task GetRoute(T model) where T : ISupportsRouting; /// /// Get the route object for an entity /// Task GetRoute(string id) where T : ISupportsRouting; /// /// Get routes for multiple entities /// Task> GetRoutes(params T[] models) where T : ISupportsRouting; /// /// Find a provider for a certain entity /// bool TryGetProvider(T model, out IRouteProvider provider) where T : ISupportsRouting; /// /// Find a provider by alias /// bool TryGetProvider(string alias, out IRouteProvider provider); }