using CryptoExchange.Net.Objects;
using System;
using System.Collections.Generic;
using System.Linq;
namespace CryptoExchange.Net.Sockets.Default.Routing
{
///
/// Message router
///
public class MessageRouter
{
private ProcessorRouter? _routingTable;
///
/// The routes registered for this router
///
public MessageRoute[] Routes { get; }
///
/// ctor
///
private MessageRouter(params MessageRoute[] routes)
{
Routes = routes;
}
private RouteCollection? GetRoutes(string typeIdentifier)
=> (_routingTable ?? throw new NullReferenceException("Routing table not build before handling")).GetRoutes(typeIdentifier);
///
/// Build the route mapping
///
public void BuildQueryRouter()
{
_routingTable = new QueryRouter(Routes);
}
///
/// Build the route mapping
///
public void BuildSubscriptionRouter()
{
_routingTable = new SubscriptionRouter(Routes);
}
///
/// Handle message
///
public bool Handle(string typeIdentifier, string? topicFilter, SocketConnection connection, DateTime receiveTime, string? originalData, object data, out CallResult? result)
{
var routeCollection = GetRoutes(typeIdentifier);
if (routeCollection == null)
throw new InvalidOperationException($"No routes for {typeIdentifier} message type");
return routeCollection.Handle(topicFilter, connection, receiveTime, originalData, data, out result);
}
///
/// Whether the router has a matching route for the specified message type and topic
///
public bool CanHandle(string typeIdentifier, string? topicFilter)
{
return GetRoutes(typeIdentifier)?.CanHandle(topicFilter) == true;
}
///
/// Create a void handler
///
public static MessageRouter CreateVoid(string typeIdentifier)
{
return new MessageRouter(new EventRoute(typeIdentifier, null, (con, time, originalData, msg) => CallResult.Ok(default!)));
}
///
/// Create a router for handling event messages
///
public static MessageRouter CreateForEvent(string typeIdentifier, Func handler, bool multipleReaders = false)
{
return new MessageRouter(new EventRoute(typeIdentifier, null, handler)
{
MultipleReaders = multipleReaders
});
}
///
/// Create a router for handling event messages
///
public static MessageRouter CreateForEvent(IEnumerable typeIdentifier, Func handler, bool multipleReaders = false)
{
return new MessageRouter(typeIdentifier.Select(x => new EventRoute(x, null, handler)
{
MultipleReaders = multipleReaders
}).ToArray());
}
///
/// Create a router for handling event messages
///
public static MessageRouter CreateForEvent(IEnumerable typeIdentifier, IEnumerable topicFilters, Func handler, bool multipleReaders = false)
{
return new MessageRouter(typeIdentifier.SelectMany(x => {
var routes = new List();
foreach (var topicFilter in topicFilters)
{
routes.Add(new EventRoute(x, topicFilter, handler)
{
MultipleReaders = multipleReaders
});
}
return routes;
}).ToArray());
}
///
/// Create a router for handling event messages
///
public static MessageRouter CreateForEvent(string typeIdentifier, string? topicFilter, Func handler, bool multipleReaders = false)
{
return new MessageRouter(new EventRoute(typeIdentifier, topicFilter, handler)
{
MultipleReaders = multipleReaders
});
}
///
/// Create a router for handling event messages
///
public static MessageRouter CreateForEvent(string typeIdentifier, IEnumerable topicFilters, Func handler, bool multipleReaders = false)
{
return new MessageRouter(topicFilters.Select(x => new EventRoute(typeIdentifier, x, handler)
{
MultipleReaders = multipleReaders
}).ToArray());
}
///
/// Create a router for handling query responses
///
public static MessageRouter CreateForQuery(IEnumerable typeIdentifier, Func?> handler, bool multipleReaders = false)
{
return new MessageRouter(typeIdentifier.Select(x => new QueryRoute(x, null, handler)
{
MultipleReaders = multipleReaders
}).ToArray());
}
///
/// Create a router for handling query responses
///
public static MessageRouter CreateForQuery(string typeIdentifier, Func?> handler, bool multipleReaders = false)
{
return new MessageRouter(new QueryRoute(typeIdentifier, null, handler)
{
MultipleReaders = multipleReaders
});
}
///
/// Create a router for handling query responses
///
public static MessageRouter CreateForQuery(string typeIdentifier, string? topicFilter, Func?> handler, bool multipleReaders = false)
{
return new MessageRouter(new QueryRoute(typeIdentifier, topicFilter, handler)
{
MultipleReaders = multipleReaders
});
}
///
/// Create a router for handling query responses
///
public static MessageRouter CreateForQuery(string typeIdentifier, Func?> handler, bool multipleReaders = false)
{
return new MessageRouter(new QueryRoute(typeIdentifier, null, handler)
{
MultipleReaders = multipleReaders
});
}
///
/// Create a router for handling query responses
///
public static MessageRouter CreateForQuery(string typeIdentifier, string? topicFilter, Func?> handler, bool multipleReaders = false)
{
return new MessageRouter(new QueryRoute(typeIdentifier, topicFilter, handler)
{
MultipleReaders = multipleReaders
});
}
///
/// Create message matcher with specific routes
///
public static MessageRouter Create(params MessageRoute[] routes)
{
return new MessageRouter(routes);
}
///
/// Whether this matcher contains a specific link
///
public bool ContainsCheck(MessageRoute route) => Routes.Any(x => x.TypeIdentifier == route.TypeIdentifier && x.TopicFilter == route.TopicFilter);
}
}