/// <summary> /// A special intermediate function for converting string chaining into real chaining. /// </summary> /// <param name="chainDataString"></param> /// <param name="search"></param> /// <param name="previousChains"></param> /// <typeparam name="S"></typeparam> /// <typeparam name="V"></typeparam> /// <returns></returns> protected Task ChainStringAsync <S, V>(ChainRequestString chainDataString, Func <S, Task <List <V> > > search, List <List <IIdView> > previousChains) where S : IConstrainedSearcher where V : IIdView { var t = timer.StartTimer($"{chainDataString.endpoint} {string.Join(".", chainDataString.chains)}"); try { var chainData = new ChainRequest <S, V>(chainDataString) { retriever = search }; try { chainData.baseSearch = JsonSerializer.Deserialize <S>(chainDataString.search, config.JsonOptions); } catch (Exception ex) { //I don't care too much about json deseralize errors, just the message. I don't even log it. throw new BadRequestException(ex.Message + " (CHAIN REMINDER: json search comes last AFTER all . chaining in a request)"); } return(ChainAsync(chainData, previousChains)); } finally { timer.EndTimer(t); } }
/// <summary> /// The major "string request" based chaining. Repeatedly call this function for every chain request /// </summary> /// <param name="request"></param> /// <param name="requester"></param> /// <param name="results"></param> /// <param name="previousResults"></param> /// <param name="fields"></param> /// <returns></returns> public Task ChainAsync(ChainRequestString data, Requester requester, List <List <IIdView> > previousResults) { if (data.endpoint == "file") { return(ChainStringAsync(data, services.file, requester, previousResults)); } else if (data.endpoint == "user") { return(ChainStringAsync(data, services.user, requester, previousResults)); } else if (data.endpoint == "content") { return(ChainStringAsync(data, services.content, requester, previousResults)); } else if (data.endpoint == "category") { return(ChainStringAsync(data, services.category, requester, previousResults)); } else if (data.endpoint == "module") { return(ChainStringAsync(data, services.module, requester, previousResults)); } else if (data.endpoint == "modulemessage") { return(ChainStringAsync(data, services.modulemessage, requester, previousResults)); } else if (data.endpoint == "comment") { return(ChainStringAsync(data, services.comment, requester, previousResults)); } else if (data.endpoint == "commentaggregate") { return(ChainStringAsync <CommentSearch, CommentAggregateView>(data, (s) => services.comment.SearchAggregateAsync(s, requester), previousResults)); } else if (data.endpoint == "activity") { return(ChainStringAsync(data, services.activity, requester, previousResults)); } else if (data.endpoint == "activityaggregate") { return(ChainStringAsync <ActivitySearch, ActivityAggregateView>(data, (s) => services.activity.SearchAggregateAsync(s, requester), previousResults)); } else if (data.endpoint == "systemaggregate") { return(ChainStringAsync <BaseSearch, SystemAggregate>(data, (s) => GetSystemAggregate(s), previousResults)); } else if (data.endpoint == "watch") { return(ChainStringAsync(data, services.watch, requester, previousResults)); } else if (data.endpoint == "vote") { return(ChainStringAsync(data, services.vote, requester, previousResults)); } else { throw new BadRequestException($"Unknown request: {data.endpoint}"); } }
/// <summary> /// Parse a specially-formatted request into a temporary chain container. The container is not complete /// </summary> /// <param name="request"></param> /// <returns></returns> public ChainRequestString ParseInitialChainString(string request) { var match = Regex.Match(request, config.RequestRegex, RegexOptions.IgnoreCase); var result = new ChainRequestString() { viewableIdentifier = request, search = match.Groups["search"].Value, endpoint = match.Groups["endpoint"].Value, name = match.Groups["name"].Value }; //Convert chaining strings into proper chaining objects. result.chains = match.Groups["chain"].Captures.Select(x => { var c = x.Value; var match = Regex.Match(c, config.ChainRegex, RegexOptions.IgnoreCase); var chaining = new Chaining() { viewableIdentifier = c, getFieldPath = match.Groups["field"].Value.Split("_".ToCharArray(), StringSplitOptions.RemoveEmptyEntries).ToList(), searchFieldPath = match.Groups["searchfield"].Value.Split("_".ToCharArray(), StringSplitOptions.RemoveEmptyEntries).ToList() }; int tempIndex = 0; if (!int.TryParse(match.Groups["index"].Value, out tempIndex)) { throw new BadRequestException($"Can't parse chain index: {match.Groups["index"]}"); } chaining.index = tempIndex; return(chaining); }); if (string.IsNullOrWhiteSpace(result.search)) { result.search = "{}"; } return(result); }
/// <summary> /// A special intermediate function for converting string chaining into real chaining. One extra step as shortcut: /// convert view service and requester to proper Func /// </summary> /// <param name="chainData"></param> /// <param name="service"></param> /// <param name="requester"></param> /// <param name="previousChains"></param> /// <typeparam name="S"></typeparam> /// <typeparam name="V"></typeparam> /// <returns></returns> protected Task ChainStringAsync <S, V>(ChainRequestString chainData, IViewReadService <V, S> service, Requester requester, List <List <IIdView> > previousChains) where S : IConstrainedSearcher where V : IIdView { return(ChainStringAsync <S, V>(chainData, (s) => service.SearchAsync(s, requester), previousChains)); }
/// <summary> /// The major "string request" based chaining. Repeatedly call this function for every chain request /// </summary> /// <param name="request"></param> /// <param name="requester"></param> /// <param name="results"></param> /// <param name="previousResults"></param> /// <param name="fields"></param> /// <returns></returns> public Task ChainAsync(ChainRequestString data, Requester requester, List <List <IIdView> > previousResults) { //This HAS to be this stupid because of the generics: referencing the service directly gives us the typing information //Don't know how to do that with reflection yet if (data.endpoint == "file") { return(ChainStringAsync(data, services.file, requester, previousResults)); } else if (data.endpoint == "user") { return(ChainStringAsync(data, services.user, requester, previousResults)); } else if (data.endpoint == "content") { return(ChainStringAsync(data, services.content, requester, previousResults)); } else if (data.endpoint == "category") { return(ChainStringAsync(data, services.category, requester, previousResults)); } else if (data.endpoint == "module") { return(ChainStringAsync(data, services.module, requester, previousResults)); } else if (data.endpoint == "modulemessage") { return(ChainStringAsync(data, services.modulemessage, requester, previousResults)); } else if (data.endpoint == "comment") { return(ChainStringAsync(data, services.comment, requester, previousResults)); } else if (data.endpoint == "activity") { return(ChainStringAsync(data, services.activity, requester, previousResults)); } else if (data.endpoint == "commentaggregate") { return(ChainStringAsync <CommentSearch, CommentAggregateView>(data, (s) => services.comment.SearchAggregateAsync(s, requester), previousResults)); } else if (data.endpoint == "activityaggregate") { return(ChainStringAsync <ActivitySearch, ActivityAggregateView>(data, (s) => services.activity.SearchAggregateAsync(s, requester), previousResults)); } else if (data.endpoint == "systemaggregate") { return(ChainStringAsync <BaseSearch, SystemAggregate>(data, (s) => GetSystemAggregate(s), previousResults)); } else if (data.endpoint == "watch") { return(ChainStringAsync(data, services.watch, requester, previousResults)); } else if (data.endpoint == "vote") { return(ChainStringAsync(data, services.vote, requester, previousResults)); } else if (data.endpoint == "ban") { return(ChainStringAsync(data, services.ban, requester, previousResults)); } else { throw new BadRequestException($"Unknown request: {data.endpoint}"); } }