using System; using System.Collections.Generic; using System.Linq; using InABox.Clients; using System.Diagnostics.CodeAnalysis; namespace InABox.Core { public interface IDigitalFormReportDataModel { public DigitalFormVariable[]? Variables { get; set; } void AddFormData(Guid formInstanceID, DFLoadStorage storage); } /// /// /// /// Should always be an EntityForm<,> public class DigitalFormReportDataModel : AutoDataModel, IDigitalFormReportDataModel where T : Entity, IRemotable, IPersistent, IDigitalFormInstance, new() { private Guid? FormId { get; set; } = null; private CoreTable? FormDataTable { get; set; } = null; private Dictionary FormData { get; set; } = new Dictionary(); //private DigitalFormVariable[]? _variables = null; public DigitalFormVariable[]? Variables { get; set; } public DigitalFormReportDataModel(Filter filter, Guid? formId = null) : base(filter) { FormId = formId; } public override string Name => "Digital Form Reports"; public void AddFormData(Guid formInstanceID, DFLoadStorage storage) { FormData.Add(formInstanceID, storage); } protected override void CheckRequiredTables(List requiredtables) { base.CheckRequiredTables(requiredtables); requiredtables.Add(TableName()); } private void LoadFormDataTable(Guid formID) { var formDataTable = new CoreTable(); formDataTable.Columns.Add(new CoreColumn { ColumnName = "Parent.ID", DataType = typeof(Guid) }); Variables ??= new Client().Load(new Filter(x => x.Form.ID).IsEqualTo(formID)); foreach (var variable in Variables) { var columns = variable.GetDisplayColumns().ToArray(); foreach (var column in columns) formDataTable.Columns.Add(column); } FormDataTable = formDataTable; AddTable("Form_Data", formDataTable, isdefault: true); LinkTable(typeof(T), "ID", "Form_Data", "Parent.ID"); } private void LoadFormDataIntoRow(CoreRow row, DFLoadStorage data) { foreach(var variable in Variables!) { var value = variable.Deserialize(data.GetEntry(variable.Code)); foreach(var (k, v) in variable.GetDisplayValues(value)) { row[k] = v; } } } protected override void AfterLoad(IEnumerable requiredtables) { base.AfterLoad(requiredtables); if(FormDataTable == null) { LoadFormDataTable(FormId ?? ExtractValues(x => x.Form.ID).FirstOrDefault()); } var idList = ExtractValues(x => x.ID); var jsonLists = ExtractValues(x => x.FormData, false).ToList(); var blobLists = ExtractValues(x => x.BlobData, false).ToList(); for(var i = 0; i < jsonLists.Count; ++i) { if (!FormData.TryGetValue(idList[i], out var formData)) { var json = jsonLists[i]; var blobJSON = blobLists[i]; formData = DigitalForm.DeserializeFormData(json, blobJSON); } var formRow = FormDataTable!.NewRow(); formRow["Parent.ID"] = idList[i]; if (formData != null) LoadFormDataIntoRow(formRow, formData); FormDataTable.Rows.Add(formRow); } Load(typeof(CoreTable), FormDataTable!, requiredtables, "Form_Data"); } public string? EvaluateExpression(string expression) { if (string.IsNullOrWhiteSpace(expression)) return null; Dictionary variables = new Dictionary(); var formrow = FormDataTable.Rows.FirstOrDefault(); foreach (var column in FormDataTable.Columns) variables[$"Data.{column.ColumnName}"] = formrow?[column.ColumnName]; var instancetable = GetTable(); var instancerow = instancetable.Rows.FirstOrDefault(); foreach (var column in instancetable.Columns) variables[$"Form.{column.ColumnName}"] = instancerow?[column.ColumnName]; var inter = typeof(T) .GetInterfaces() .FirstOrDefault(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IDigitalFormInstance<>)); if (inter != null) { var link = inter.GenericTypeArguments[0]; var entityLinkDef = link.GetSuperclassDefinition(typeof(EntityLink<>)); if (entityLinkDef != null) { var entityType = entityLinkDef.GenericTypeArguments[0]; var parenttablename = $"{DataModel.TableName(typeof(T))}_{DataModel.TableName(entityType)}"; var entitytable = GetDataModelTable(parenttablename); if (entitytable != null) { foreach (var column in entitytable.Table.Columns) variables[$"{entityType.EntityName().Split('.').Last()}.{column.ColumnName}"] = instancerow?[column.ColumnName]; } } } var exp = new CoreExpression(expression); return exp.Evaluate(variables)?.ToString(); } } }