2021-11-19 16:11:12 +01:00
|
|
|
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<Routes> Logger { get; set; }
|
|
|
|
|
protected IEnumerable<IRouteProvider> Providers { get; set; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public Routes(IZeroContext context, IZeroStore store, ILogger<Routes> logger, IEnumerable<IRouteProvider> providers)
|
|
|
|
|
{
|
|
|
|
|
Context = context;
|
|
|
|
|
Store = store;
|
|
|
|
|
Logger = logger;
|
|
|
|
|
Providers = providers;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <inheritdoc />
|
2021-12-01 15:54:11 +01:00
|
|
|
public async Task<string> GetUrl<T>(T model) where T : ISupportsRouting => (await GetRoute(model))?.Url;
|
2021-11-19 16:11:12 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <inheritdoc />
|
2021-12-01 15:54:11 +01:00
|
|
|
public async Task<string> GetUrl<T>(string id) where T : ISupportsRouting => (await GetRoute<T>(id))?.Url;
|
2021-11-19 16:11:12 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <inheritdoc />
|
2021-12-01 15:54:11 +01:00
|
|
|
public async Task<Dictionary<T, string>> GetUrls<T>(params T[] models) where T : ISupportsRouting => (await GetRoutes(models)).ToDictionary(x => x.Key, x => x.Value?.Url);
|
2021-11-19 16:11:12 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <inheritdoc />
|
2021-12-01 15:54:11 +01:00
|
|
|
public async Task<Route> GetRoute<T>(string id) where T : ISupportsRouting
|
2021-11-19 16:11:12 +01:00
|
|
|
{
|
|
|
|
|
T model = await GetContext().Session.LoadAsync<T>(id);
|
|
|
|
|
return await GetRoute(model);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <inheritdoc />
|
2021-12-01 15:54:11 +01:00
|
|
|
public async Task<Route> GetRoute<T>(T model) where T : ISupportsRouting
|
2021-11-19 16:11:12 +01:00
|
|
|
{
|
|
|
|
|
if (model == null)
|
|
|
|
|
{
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!TryGetProvider(model, out IRouteProvider routeProvider))
|
|
|
|
|
{
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RoutingContext context = GetContext();
|
|
|
|
|
return await FindRoute(routeProvider, context, model);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <inheritdoc />
|
2021-12-01 15:54:11 +01:00
|
|
|
public async Task<Dictionary<T, Route>> GetRoutes<T>(params T[] models) where T : ISupportsRouting
|
2021-11-19 16:11:12 +01:00
|
|
|
{
|
|
|
|
|
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();
|
2021-12-01 15:54:11 +01:00
|
|
|
return (await routeProvider.Find(context, models.Select(x => (ISupportsRouting)x).ToArray())).ToDictionary(x => (T)x.Key, x => x.Value);
|
2021-11-19 16:11:12 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <inheritdoc />
|
2021-12-01 15:54:11 +01:00
|
|
|
public virtual bool TryGetProvider<T>(T model, out IRouteProvider provider) where T : ISupportsRouting
|
2021-11-19 16:11:12 +01:00
|
|
|
{
|
|
|
|
|
Type type = model.GetType();
|
|
|
|
|
provider = Providers.OrderByDescending(x => x.Priority).FirstOrDefault(x => x.CanHandle(type));
|
|
|
|
|
return provider != null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <inheritdoc />
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Map a route to an MVC endpoint
|
|
|
|
|
/// </summary>
|
|
|
|
|
//public virtual RouteProviderEndpoint MapEndpoint(IResolvedRoute route)
|
|
|
|
|
//{
|
|
|
|
|
// IEnumerable<Func<IResolvedRoute, RouteProviderEndpoint>> resolvers = Options.Routing.EndpointResolvers.GetAll(route.GetType());
|
|
|
|
|
|
|
|
|
|
// foreach (Func<IResolvedRoute, RouteProviderEndpoint> resolver in resolvers.Reverse())
|
|
|
|
|
// {
|
|
|
|
|
// RouteProviderEndpoint endpoint = resolver(route);
|
|
|
|
|
|
|
|
|
|
// if (endpoint != null)
|
|
|
|
|
// {
|
|
|
|
|
// return endpoint;
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// return Options.Routing.DefaultEndpoint;
|
|
|
|
|
//}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Find a persisted route for an entity
|
|
|
|
|
/// </summary>
|
2021-12-01 15:54:11 +01:00
|
|
|
protected virtual async Task<Route> FindRoute(IRouteProvider provider, RoutingContext context, ISupportsRouting model)
|
2021-11-19 16:11:12 +01:00
|
|
|
{
|
|
|
|
|
return await provider.Find(context, model);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Build a new routing context
|
|
|
|
|
/// </summary>
|
|
|
|
|
protected virtual RoutingContext GetContext()
|
|
|
|
|
{
|
|
|
|
|
return new(Store, Context, Store.Session());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public interface IRoutes
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Get the URL for an entity
|
|
|
|
|
/// </summary>
|
2021-12-01 15:54:11 +01:00
|
|
|
Task<string> GetUrl<T>(T model) where T : ISupportsRouting;
|
2021-11-19 16:11:12 +01:00
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Get the URL for an entity
|
|
|
|
|
/// </summary>
|
2021-12-01 15:54:11 +01:00
|
|
|
Task<string> GetUrl<T>(string id) where T : ISupportsRouting;
|
2021-11-19 16:11:12 +01:00
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Get URLs for multiple entities
|
|
|
|
|
/// </summary>
|
2021-12-01 15:54:11 +01:00
|
|
|
Task<Dictionary<T, string>> GetUrls<T>(params T[] models) where T : ISupportsRouting;
|
2021-11-19 16:11:12 +01:00
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Get the route object for an entity
|
|
|
|
|
/// </summary>
|
2021-12-01 15:54:11 +01:00
|
|
|
Task<Route> GetRoute<T>(T model) where T : ISupportsRouting;
|
2021-11-19 16:11:12 +01:00
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Get the route object for an entity
|
|
|
|
|
/// </summary>
|
2021-12-01 15:54:11 +01:00
|
|
|
Task<Route> GetRoute<T>(string id) where T : ISupportsRouting;
|
2021-11-19 16:11:12 +01:00
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Get routes for multiple entities
|
|
|
|
|
/// </summary>
|
2021-12-01 15:54:11 +01:00
|
|
|
Task<Dictionary<T, Route>> GetRoutes<T>(params T[] models) where T : ISupportsRouting;
|
2021-11-19 16:11:12 +01:00
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Find a provider for a certain entity
|
|
|
|
|
/// </summary>
|
2021-12-01 15:54:11 +01:00
|
|
|
bool TryGetProvider<T>(T model, out IRouteProvider provider) where T : ISupportsRouting;
|
2021-11-19 16:11:12 +01:00
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Find a provider by alias
|
|
|
|
|
/// </summary>
|
|
|
|
|
bool TryGetProvider(string alias, out IRouteProvider provider);
|
|
|
|
|
}
|