using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Timers; using InABox.Core; namespace InABox.Clients { public enum SerializerProtocol { Rest } public class QueryMultipleResults { private readonly Dictionary Results; internal QueryMultipleResults(Dictionary results) { Results = results; } public CoreTable this[string name] => Results[name]; public CoreTable Get() => Results[typeof(T).Name]; public CoreTable Get(string name) => Results[name]; } public abstract class Client { public abstract CoreTable Query(IFilter? filter = null, IColumns? columns = null, ISortOrder? sortOrder = null); public abstract void Save(Entity entity, string auditNote); private static IClient CheckClient() { using (new Profiler(true)) return ClientFactory.CreateClient(); } public static Dictionary QueryMultiple(Dictionary queries) { try { using var timer = new Profiler(false); var result = CheckClient().QueryMultiple(queries); timer.Log(result.Sum(x => x.Value.Rows.Count)); return result; } catch (RequestException e) { ClientFactory.RaiseRequestError(e); throw; } } public static QueryMultipleResults QueryMultiple(params IKeyedQueryDef[] queries) { try { using var timer = new Profiler(false); var result = CheckClient().QueryMultiple(queries.ToDictionary(x => x.Key, x => x as IQueryDef)); timer.Log(result.Sum(x => x.Value.Rows.Count)); return new QueryMultipleResults(result); } catch (RequestException e) { ClientFactory.RaiseRequestError(e); throw; } } public static QueryMultipleResults QueryMultiple(IEnumerable queries) { try { using var timer = new Profiler(false); var result = CheckClient().QueryMultiple(queries.ToDictionary(x => x.Key, x => x as IQueryDef)); timer.Log(result.Sum(x => x.Value.Rows.Count)); return new QueryMultipleResults(result); } catch (RequestException e) { ClientFactory.RaiseRequestError(e); throw; } } public static ValidationData Validate(Guid session) { try { using (new Profiler(true)) return CheckClient().Validate(session); } catch (RequestException e) { ClientFactory.RaiseRequestError(e); throw; } } public static ValidationData Validate(string pin, Guid session = default) { try { using (new Profiler(true)) return CheckClient().Validate(pin, session); } catch (RequestException e) { ClientFactory.RaiseRequestError(e); throw; } } public static ValidationData Validate(string userid, string password, Guid session = default) { try { using (new Profiler(true)) return CheckClient().Validate(userid, password, session); } catch (RequestException e) { ClientFactory.RaiseRequestError(e); throw; } } public static bool Check2FA(string code, Guid? session = null) { try { using (new Profiler(true)) return CheckClient().Check2FA(code, session); } catch (RequestException e) { ClientFactory.RaiseRequestError(e); throw; } } public static bool Ping() { try { using (new Profiler(true)) return CheckClient().Ping(); } catch (RequestException e) { ClientFactory.RaiseRequestError(e); throw; } } public static DatabaseInfo Info() { try { using (new Profiler(true)) return CheckClient().Info(); } catch (RequestException e) { ClientFactory.RaiseRequestError(e); throw; } } public static Client Create(Type TEntity) => (Activator.CreateInstance(typeof(Client<>).MakeGenericType(TEntity)) as Client)!; } public class Client : Client, IDisposable where TEntity : Entity, IPersistent, IRemotable, new() { private IClient _client; public Client() { _client = ClientFactory.CreateClient(); } public void Dispose() { } private void CheckSupported() { if (!ClientFactory.IsSupported()) throw new NotSupportedException(string.Format("{0} is not supported in this context", typeof(TEntity).EntityName())); } private string FilterToString(Filter filter) { return filter != null ? filter.AsOData() : ""; } private string OrderToString(SortOrder order) { return order != null ? order.AsOData() : ""; } public CoreTable Query(Filter? filter = null, Columns? columns = null, SortOrder? orderby = null) { try { using (var timer = new Profiler(false)) { CheckSupported(); var result = _client.Query(filter, columns, orderby); timer.Log(result.Rows.Count); return result; } } catch(RequestException e) { ClientFactory.RaiseRequestError(e); throw; } } public override CoreTable Query(IFilter? filter, IColumns? columns, ISortOrder? sortOrder) { return Query(filter as Filter, columns as Columns, sortOrder as SortOrder); } public void Query(Filter? filter, Columns? columns, SortOrder? sort, Action callback) { try { var timer = new Profiler(false); CheckSupported(); _client.Query(filter, columns, sort, (c, e) => { timer.Dispose(c != null ? c.Rows.Count : -1); callback?.Invoke(c, e); }); } catch (RequestException e) { ClientFactory.RaiseRequestError(e); throw; } } public TEntity[] Load(Filter? filter = null, SortOrder? sort = null) { try { using (var timer = new Profiler(false)) { CheckSupported(); var result = _client.Load(filter, sort); foreach (var entity in result) entity.CommitChanges(); timer.Log(result.Length); return result; } } catch (RequestException e) { ClientFactory.RaiseRequestError(e); throw; } } public void Load(Filter filter, SortOrder sort, Action callback) { try { var timer = new Profiler(false); CheckSupported(); _client.Load(filter, sort, (i, e) => { timer.Dispose(i != null ? i.Length : -1); callback?.Invoke(i, e); }); } catch (RequestException e) { ClientFactory.RaiseRequestError(e); throw; } } public override void Save(Entity entity, string auditNote) { try { Save((entity as TEntity)!, auditNote); } catch (RequestException e) { ClientFactory.RaiseRequestError(e); throw; } } public void Save(TEntity entity, string auditnote) { try { using (new Profiler(true)) { CheckSupported(); entity.LastUpdate = DateTime.Now; entity.LastUpdateBy = ClientFactory.UserID; _client.Save(entity, auditnote); entity.CommitChanges(); } } catch (RequestException e) { ClientFactory.RaiseRequestError(e); throw; } } public void Save(TEntity entity, string auditnote, Action callback) { try { var timer = new Profiler(false); CheckSupported(); _client.Save(entity, auditnote, (i, c) => { timer.Dispose(); callback?.Invoke(i, c); }); } catch (RequestException e) { ClientFactory.RaiseRequestError(e); throw; } } public void Save(IEnumerable entities, string auditnote) { try { using var timer = new Profiler(false); CheckSupported(); if (entities.Any()) _client.Save(entities, auditnote); timer.Log(entities.Count()); } catch (RequestException e) { ClientFactory.RaiseRequestError(e); throw; } } public void Save(IEnumerable entities, string auditnote, Action, Exception?> callback) { try { var timer = new Profiler(false); CheckSupported(); if (entities.Any()) _client.Save(entities, auditnote, (i, e) => { timer.Dispose(i.Count()); callback?.Invoke(i, e); }); } catch (RequestException e) { ClientFactory.RaiseRequestError(e); throw; } } public void Delete(TEntity entity, string auditnote) { try { using (new Profiler(true)) { CheckSupported(); _client.Delete(entity, auditnote); } } catch (RequestException e) { ClientFactory.RaiseRequestError(e); throw; } } public void Delete(TEntity entity, string auditnote, Action callback) { try { var timer = new Profiler(true); CheckSupported(); _client.Delete(entity, auditnote, (i, e) => { timer.Dispose(); callback?.Invoke(i, e); }); } catch (RequestException e) { ClientFactory.RaiseRequestError(e); throw; } } public void Delete(IList entities, string auditnote) { try { using var timer = new Profiler(false); CheckSupported(); _client.Delete(entities, auditnote); timer.Log(entities.Count()); } catch (RequestException e) { ClientFactory.RaiseRequestError(e); throw; } } public void Delete(IList entities, string auditnote, Action, Exception?> callback) { try { var timer = new Profiler(false); CheckSupported(); _client.Delete(entities, auditnote, (i, e) => { timer.Dispose(entities.Count()); callback?.Invoke(i, e); }); } catch (RequestException e) { ClientFactory.RaiseRequestError(e); throw; } } public IEnumerable SupportedTypes() { try { using (new Profiler(true)) return _client.SupportedTypes(); } catch (RequestException e) { ClientFactory.RaiseRequestError(e); throw; } } public new DatabaseInfo Info() { try { using (new Profiler(true)) return _client.Info(); } catch (RequestException e) { ClientFactory.RaiseRequestError(e); throw; } } } }