using Pilz.Data; using Pilz.Extensions.Reflection; using Pilz.Net.Extensions; using System.Diagnostics; using System.Net; namespace Pilz.Net.Api.Server; public abstract class BaseChildItemHandler(IApiServer server) : BaseHandler(server) where TEntity : class, IDataObject where TParent : class, IDataObject where TUpdateMsg : ApiMessage { public class ChildEntityUpdate(TEntity entity, Func getParent, TUpdateMsg message, ApiRequestInfo reqest) : EntityUpdate(entity, message, reqest) { private readonly Func getParent = getParent; private TParent? parent; public TParent? Parent => parent ??= getParent(); } protected virtual bool RegisterGetAll => true; protected virtual bool RegisterPost => true; public override void Initialize(IApiServer server) { base.Initialize(server); var t = GetType(); if (RegisterGetAll) server.RegisterHandler(t.GetMethod(nameof(GetAll))!.CreateDelegate(this), new(Route, "GET"), Debugger.IsAttached); if (RegisterPost) server.RegisterHandler(t.GetMethod(nameof(Post))!.CreateDelegate(this), new(Route, "POST"), Debugger.IsAttached); } public virtual ApiResult GetAll(int parent) { IQueryable list; if (parent != 0) { if (!server.Manager.Find(parent, out TParent? parentEntity)) return ApiResult.NotFound(); list = GetChilds(parentEntity).AsQueryable(); } else list = server.Manager.Get(); return SortEntities(list).ToList().Select(ToClient).ToItemsResult(); } public virtual ApiResult Post(int parent, TUpdateMsg msg, ApiRequestInfo req) { if (!server.Manager.Find(parent, out TParent? parentEntity)) return ApiResult.NotFound(); var entity = CreateNewEntity(msg, parentEntity); var update = new ChildEntityUpdate(entity, () => parentEntity, msg, req); if (UpdateEntity(update) is ApiResult result) return result; GetChilds(parentEntity).Add(entity); if (OnSave(update) is ApiResult result2) return result2; return ToClient(entity).ToItemResult(HttpStatusCode.Created); } public override ApiResult Put(int id, TUpdateMsg msg, ApiRequestInfo req) { if (!server.Manager.Find(id, out TEntity? entity)) return ApiResult.NotFound(); var update = new ChildEntityUpdate(entity, () => server.Manager.Get().AsEnumerable().FirstOrDefault(n => GetChilds(n).Any(n => n.Id == id)), msg, req); if (UpdateEntity(update) is ApiResult result) return result; if (OnSave(update) is ApiResult result2) return result2; return ToClient(entity).ToItemResult(); } protected virtual TEntity CreateNewEntity(TUpdateMsg msg, TParent parent) { return CreateNewEntity(msg); } protected override ApiResult? OnSave(EntityUpdate update) { if (update.Entity.Id == 0 && update is ChildEntityUpdate updateEx && updateEx.Parent != null) { server.Manager.Save(updateEx.Parent, true); return null; } else return base.OnSave(update); } public abstract IList GetChilds(TParent parent); protected virtual IQueryable SortEntities(IQueryable entities) { return entities; } }