using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using InABox.Clients; namespace InABox.Core { public class MultiQuery { private readonly List _queries = new List(); public int Count => _queries.Count; public Dictionary Definitions() { Dictionary result = new Dictionary(); foreach (var query in _queries) result[query.Key] = query.Query; return result; } public Dictionary Results() { Dictionary result = new Dictionary(); foreach (var query in _queries) result[query.Key] = query.Result; return result; } public void Clear() { _queries.Clear(); } public void Add(IQueryDef query, object key) { if (key == null) throw new Exception("MultiQuery Key many not be null"); if (_queries.Any(x => Equals(x.Key, key))) throw new Exception("Key already exists"); _queries.Add(new InternalQueryDef { Key = key, Query = query }); } public void Query(Action callback = null) { var tasks = new Dictionary, object>(); foreach (var query in _queries) { var task = Task.Run( () => { var client = ClientFactory.CreateClient(query.Query.Type); return client.Query(query.Query.Filter, query.Query.Columns, query.Query.SortOrder); } ); tasks[task] = query.Key; } if (callback == null) { Task.WaitAll(tasks.Keys.ToArray()); foreach (var task in tasks.Keys) { var query = _queries.FirstOrDefault(x => Equals(x.Key, tasks[task])); query.Result = task.Result; } } else { Task.WhenAll(tasks.Keys.ToArray()).ContinueWith(t => { foreach (var task in tasks.Keys) { var query = _queries.FirstOrDefault(x => Equals(x.Key, tasks[task])); query.Result = task.Result; } callback.Invoke(this); }); } } public bool Contains(object key) { return _queries.Any(x => Equals(x.Key, key)); } public CoreTable Get(object key) { var query = _queries.FirstOrDefault(x => Equals(x.Key, key)); if (query == null) throw new Exception("Key does not exist"); if (query.Result == null) throw new Exception("No result available"); return query.Result; } public void Set(object key, CoreTable table) { var query = _queries.FirstOrDefault(x => Equals(x.Key, key)); if (query == null) throw new Exception("Key does not exist"); query.Result = table; } private class InternalQueryDef { public object Key { get; set; } public IQueryDef Query { get; set; } public CoreTable Result { get; set; } public Entity[] Updates { get; set; } } #region Simplified Generic Helpers public void Add(Filter? filter = null, Columns? columns = null, SortOrder? sort = null) where T : Entity, IRemotable, IPersistent, new() { Add(new QueryDef(filter, columns, sort), typeof(T)); } public CoreTable Get() { return Get(typeof(T)); } public bool Contains() { return Contains(typeof(T)); } #endregion } }