using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace InABox.Core { public interface IEntityFormUtils { public abstract bool CanEditForm(IDigitalFormInstance form, Entity entity); public abstract Entity NewEntity(DigitalForm form); public abstract void OnSave(IDigitalFormInstance form, Entity entity); } public abstract class EntityFormUtils : IEntityFormUtils where TForm : EntityForm where TEntity : Entity, new() where TEntityLink : EntityLink, new() { public abstract bool CanEditForm(TForm form, TEntity entity); public abstract TEntity NewEntity(DigitalForm form); public abstract void OnSave(TForm form, TEntity entity); void IEntityFormUtils.OnSave(IDigitalFormInstance form, Entity entity) => OnSave((TForm)form, (TEntity)entity); bool IEntityFormUtils.CanEditForm(IDigitalFormInstance form, Entity entity) => CanEditForm((form as TForm)!, (entity as TEntity)!); Entity IEntityFormUtils.NewEntity(DigitalForm form) => NewEntity(form); } public class DelegateEntityFormUtils : EntityFormUtils where TForm : EntityForm where TEntity : Entity, new() where TEntityLink : EntityLink, new() { public delegate bool CanEditEvent(TForm form, TEntity entity); public delegate TEntity NewEntityEvent(DigitalForm form); public delegate void OnSaveEvent(TForm form, TEntity entity); public CanEditEvent OnCanEdit; public NewEntityEvent? OnNewEntity; public OnSaveEvent? SaveEvent; public DelegateEntityFormUtils(CanEditEvent canEditForm, NewEntityEvent? onNewEntity = null, OnSaveEvent? onSave = null) { OnCanEdit = canEditForm; OnNewEntity = onNewEntity; SaveEvent = onSave; } public override bool CanEditForm(TForm form, TEntity entity) => OnCanEdit(form, entity); public override TEntity NewEntity(DigitalForm form) => OnNewEntity?.Invoke(form) ?? new TEntity(); public override void OnSave(TForm form, TEntity entity) => SaveEvent?.Invoke(form, entity); } public static class DFUtils { private static List? _fieldTypes; public static List GetFieldTypes(bool includeObsolete = false) { _fieldTypes ??= CoreUtils.Entities.Where(x => x.IsClass && !x.IsGenericType && x.HasInterface()).ToList(); return includeObsolete ? _fieldTypes : _fieldTypes.Where(x => !x.HasInterface()).ToList(); } public static Type? GetFieldType(string typeName) { var type = GetFieldTypes(true).Where(x => x.FullName == typeName).FirstOrDefault(); if(type != null) return type; if(Enum.TryParse(typeName, out DigitalFormVariableType variableType)) { // For the old types switch (variableType) { case DigitalFormVariableType.String: return typeof(DFLayoutStringField); case DigitalFormVariableType.Boolean: return typeof(DFLayoutBooleanField); case DigitalFormVariableType.Integer: return typeof(DFLayoutIntegerField); case DigitalFormVariableType.Double: return typeof(DFLayoutDoubleField); case DigitalFormVariableType.Date: return typeof(DFLayoutDateField); case DigitalFormVariableType.Time: return typeof(DFLayoutTimeField); case DigitalFormVariableType.Choice: return typeof(DFLayoutOptionField); case DigitalFormVariableType.Lookup: return typeof(DFLayoutLookupField); case DigitalFormVariableType.SignaturePad: return typeof(DFLayoutSignaturePad); case DigitalFormVariableType.EmbeddedImage: return typeof(DFLayoutEmbeddedImage); case DigitalFormVariableType.MultiImage: return typeof(DFLayoutMultiImage); } } return null; } private static Dictionary>? _formInstanceTypes; private static Dictionary> FormInstanceTypes { get { _formInstanceTypes ??= CoreUtils.Entities.Where(x => x.HasInterface()) .Select(x => { var inter = x.GetInterfaceDefinition(typeof(IDigitalFormInstance<>)); if (inter != null) { var link = inter.GenericTypeArguments[0]; var entityLinkDef = link.GetSuperclassDefinition(typeof(EntityLink<>)); if (entityLinkDef != null) { var entityType = entityLinkDef.GenericTypeArguments[0]; return new Tuple(entityType.Name, x, entityType); } } return null; }).Where(x => x != null).ToDictionary(x => x!.Item1, x => new Tuple(x!.Item2, x!.Item3)); return _formInstanceTypes; } } public static IEnumerable GetFormInstanceTypes() { return FormInstanceTypes.Select(x => x.Value.Item1); } public static Type? GetFormInstanceType(string appliesTo) { if (FormInstanceTypes.TryGetValue(appliesTo, out var result)) { return result.Item1; } return null; } private static Dictionary _formUtils = new Dictionary(); public static void AddFormUtils( DelegateEntityFormUtils.CanEditEvent editFormFunc, DelegateEntityFormUtils.NewEntityEvent? newEntityFunc = null, DelegateEntityFormUtils.OnSaveEvent? beforeSaveFunc = null) where TForm : EntityForm where TEntity : Entity, new() where TEntityLink : EntityLink, new() { _formUtils.Add(typeof(TForm), new DelegateEntityFormUtils(editFormFunc, newEntityFunc, beforeSaveFunc)); } public static void AddFormUtils(EntityFormUtils formUtils) where TForm : EntityForm where TEntity : Entity, new() where TEntityLink : EntityLink, new() { _formUtils.Add(typeof(TForm), formUtils); } public static bool CanEditForm(Type TForm, IDigitalFormInstance Form, Entity Entity) { if(_formUtils.TryGetValue(TForm, out var utils)) { return utils.CanEditForm(Form, Entity); } return false; } public static bool CanEditForm(TForm Form, TEntity Entity) where TForm : EntityForm where TEntity : Entity, new() where TEntityLink : EntityLink, new() { return CanEditForm(typeof(TForm), Form, Entity); } public static Entity NewEntity(Type TForm, Type TEntity, DigitalForm form) { if (_formUtils.TryGetValue(TForm, out var utils)) { return utils.NewEntity(form); } return (Activator.CreateInstance(TEntity) as Entity)!; } public static TEntity NewEntity(DigitalForm form) where TForm : EntityForm where TEntity : Entity, new() where TEntityLink : EntityLink, new() { return (TEntity)NewEntity(typeof(TForm), typeof(TEntity), form); } public static void OnSave(Type TForm, IDigitalFormInstance form, Entity entity) { if (_formUtils.TryGetValue(TForm, out var utils)) { utils.OnSave(form, entity); } } public static void OnSave(TForm form, TEntity entity) where TForm : EntityForm where TEntity : Entity, new() where TEntityLink : EntityLink, new() { OnSave(typeof(TForm), form, entity); } public static Type? FormEntityType(DigitalForm form) { return FormEntityType(form.AppliesTo); } public static Type? FormEntityType(string appliesTo) { return CoreUtils.Entities.FirstOrDefault(x => string.Equals(x.Name, appliesTo)); } public static Type FormEntityLinkType(Type TForm) { var formInstanceType = TForm.GetInterfaceDefinition(typeof(IDigitalFormInstance<>)) ?? throw new Exception("Form does not implement IDigitalFormInstance<>"); return formInstanceType.GenericTypeArguments[0]; } public static Type FormEntityType(Type TForm) { var linkType = FormEntityLinkType(TForm); var linkInterface = linkType.GetInterfaceDefinition(typeof(IEntityLink<>)); return linkInterface!.GenericTypeArguments[0]; } /*public static IEntityLink GetParentLink(IDigitalFormInstance formInstance) { var parentlink = CoreUtils.HasProperty(formInstance.GetType(), "Parent") ? CoreUtils.GetPropertyValue(formInstance, "Parent") as IEntityLink : null; }*/ public static IColumns RequiredEntityColumns(Type TEntity, IEnumerable variables) { var entityColumns = LookupFactory.RequiredColumns(TEntity); foreach(var variable in variables) { var property = variable.GetProperties().Property; if (!property.IsNullOrWhiteSpace()) { entityColumns.Add(property); } } return entityColumns; } public static Columns EntityColumns(IEnumerable variables) => (RequiredEntityColumns(typeof(TEntity), variables) as Columns)!; } }