COA.EnterpriseServices/COA.EnterpriseServices.DataAccess.QuickBase/FieldMapRegistry.cs
2020-10-15 20:47:32 -04:00

150 lines
5.8 KiB
C#

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<FieldMap> fieldRegistry = new List<FieldMap>();
private static readonly IDictionary<Type, string> tableRegistry = new Dictionary<Type, string>();
static FieldMapRegistry()
{
AddTable<Creditor, CreditorsFieldMap>()
.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<Entities.Client, ClientFieldMap>()
.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);
}
/// <summary>
/// Adds a table mapping for a QuickBase field map
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <typeparam name="TEnumFieldMap"></typeparam>
/// <returns></returns>
private static TableMap<TEntity, TEnumFieldMap> AddTable<TEntity, TEnumFieldMap>() where TEntity : IRecord
{
var tableNameAttribute = typeof(TEnumFieldMap).GetCustomAttribute<QuickBaseNameAttribute>();
if (tableNameAttribute != null)
{
tableRegistry.Add(typeof(TEntity), tableNameAttribute.Name);
}
return default;
}
/// <summary>
/// Adds default property mappings for common fields
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <typeparam name="TEnumFieldMap"></typeparam>
/// <param name="table"></param>
/// <returns></returns>
internal static TableMap<TEntity, TEnumFieldMap> WithDefaults<TEntity, TEnumFieldMap>(this TableMap<TEntity, TEnumFieldMap> 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;
}
/// <summary>
/// Adds a propert mapping for an entity property
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <typeparam name="TEnumFieldMap"></typeparam>
/// <param name="table"></param>
/// <param name="property"></param>
/// <param name="field"></param>
/// <returns></returns>
internal static TableMap<TEntity, TEnumFieldMap> WithProperty<TEntity, TEnumFieldMap>(this TableMap<TEntity, TEnumFieldMap> table, Expression<Func<TEntity, object>> property, TEnumFieldMap field)
{
if (property.Body is MemberExpression memberExpression)
{
fieldRegistry.Add(new FieldMap
{
ItemType = memberExpression.Member.DeclaringType,
PropertyName = memberExpression.Member.Name,
FieldId = field.To<int>()
});
}
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<int>()
});
}
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<int, object>(fieldId.Value, value));
}
}
return context;
}
}
}