using COA.Common; using COA.EnterpriseServices.DataAccess.Entities; using COA.PartnerApis.QuickBase; using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Reflection; namespace COA.EnterpriseServices.DataAccess.QuickBase { internal static class FieldMapRegistry { private static readonly ICollection fieldRegistry = new List(); private static readonly IDictionary tableRegistry = new Dictionary(); static FieldMapRegistry() { AddTable() .WithDefaults() .WithProperty(c => c.Status, CreditorsFieldMap.CreditorStatus) .WithProperty(c => c.ClientFirstName, CreditorsFieldMap.ClientFirstName) .WithProperty(c => c.ClientLastName, CreditorsFieldMap.ClientLastName) .WithProperty(c => c.CurrentCreditorProfileId, CreditorsFieldMap.RelatedCurrentCreditorPrimary) .WithProperty(c => c.OriginalCreditorProfileId, CreditorsFieldMap.RelatedOriginalCreditor) .WithProperty(c => c.AccountNumber, CreditorsFieldMap.AccountNum); AddTable() .WithDefaults() .WithProperty(c => c.FirstName, ClientFieldMap.FirstName) .WithProperty(c => c.LastName, ClientFieldMap.LastName) .WithProperty(c => c.Email, ClientFieldMap.ClientPrimaryEmail) .WithProperty(c => c.Phone, ClientFieldMap.ClientPrimaryPhone); } /// /// Adds a table mapping for a QuickBase field map /// /// /// /// private static TableMap AddTable() where TEntity : IRecord { var tableNameAttribute = typeof(TEnumFieldMap).GetCustomAttribute(); if (tableNameAttribute != null) { tableRegistry.Add(typeof(TEntity), tableNameAttribute.Name); } return default; } /// /// Adds default property mappings for common fields /// /// /// /// /// internal static TableMap WithDefaults(this TableMap table) where TEntity : IRecord where TEnumFieldMap : Enum { fieldRegistry.Add(new FieldMap { ItemType = typeof(TEntity), PropertyName = nameof(IRecord.Id), FieldId = PartnerApis.QuickBase.Constants.RecordIdFieldId }); fieldRegistry.Add(new FieldMap { ItemType = typeof(TEntity), PropertyName = nameof(IRecord.Created), FieldId = PartnerApis.QuickBase.Constants.DateCreatedFieldId }); fieldRegistry.Add(new FieldMap { ItemType = typeof(TEntity), PropertyName = nameof(IRecord.Modified), FieldId = PartnerApis.QuickBase.Constants.DateModifiedFieldId }); return default; } /// /// Adds a propert mapping for an entity property /// /// /// /// /// /// /// internal static TableMap WithProperty(this TableMap table, Expression> property, TEnumFieldMap field) { if (property.Body is MemberExpression memberExpression) { fieldRegistry.Add(new FieldMap { ItemType = memberExpression.Member.DeclaringType, PropertyName = memberExpression.Member.Name, FieldId = field.To() }); } else if (property.Body is UnaryExpression unaryExpression && unaryExpression.Operand is MemberExpression unaryMemberExpression) { fieldRegistry.Add(new FieldMap { ItemType = unaryMemberExpression.Member.DeclaringType, PropertyName = unaryMemberExpression.Member.Name, FieldId = field.To() }); } return default; } internal static int? GetFieldId(PropertyInfo info) { var map = fieldRegistry.FirstOrDefault(m => m.ItemType == info.DeclaringType && m.PropertyName == info.Name); return map != null ? map.FieldId : default; } internal static QuickBaseRecordContext GetTableContext(object item) { var context = new QuickBaseRecordContext(); var itemType = item.GetType(); var properties = itemType.GetProperties(); context.Table = tableRegistry.FirstOrDefault(r => r.Key == itemType).Value; foreach (var property in properties) { var fieldId = GetFieldId(property); var value = property.GetValue(item); if (fieldId != null) { context.FieldIds.Add(new KeyValuePair(fieldId.Value, value)); } } return context; } } }