/// <summary>
/// Gets the merge object list for the current EntitySet
/// </summary>
/// <param name="rockContext">The rock context.</param>
/// <param name="fetchCount">The fetch count.</param>
/// <returns></returns>
private List<object> GetMergeObjectList( RockContext rockContext, int? fetchCount = null )
{
int entitySetId = hfEntitySetId.Value.AsInteger();
var entitySetService = new EntitySetService( rockContext );
var entitySet = entitySetService.Get( entitySetId );
Dictionary<int, object> mergeObjectsDictionary = new Dictionary<int, object>();
// If this EntitySet contains IEntity Items, add those first
if ( entitySet.EntityTypeId.HasValue )
{
var qryEntity = entitySetService.GetEntityQuery( entitySetId );
if ( fetchCount.HasValue )
{
qryEntity = qryEntity.Take( fetchCount.Value );
}
var entityTypeCache = EntityTypeCache.Read( entitySet.EntityTypeId.Value );
bool isPersonEntityType = entityTypeCache != null && entityTypeCache.Guid == Rock.SystemGuid.EntityType.PERSON.AsGuid();
bool isGroupMemberEntityType = entityTypeCache != null && entityTypeCache.Guid == Rock.SystemGuid.EntityType.GROUP_MEMBER.AsGuid();
bool combineFamilyMembers = cbCombineFamilyMembers.Visible && cbCombineFamilyMembers.Checked;
if ( ( isGroupMemberEntityType || isPersonEntityType ) && combineFamilyMembers )
{
IQueryable<IEntity> qryPersons;
if ( isGroupMemberEntityType )
{
qryPersons = qryEntity.OfType<GroupMember>().Select( a => a.Person ).Distinct();
}
else
{
qryPersons = qryEntity;
}
Guid familyGroupType = Rock.SystemGuid.GroupType.GROUPTYPE_FAMILY.AsGuid();
var qryFamilyGroupMembers = new GroupMemberService( rockContext ).Queryable()
.Where( a => a.Group.GroupType.Guid == familyGroupType )
.Where( a => qryPersons.Any( aa => aa.Id == a.PersonId ) );
var qryCombined = qryFamilyGroupMembers.Join(
qryPersons,
m => m.PersonId,
p => p.Id,
( m, p ) => new { GroupMember = m, Person = p } )
.GroupBy( a => a.GroupMember.GroupId )
.Select( x => new
{
GroupId = x.Key,
Persons = x.Select( xx => xx.Person ).Distinct()
} );
foreach ( var combinedFamilyItem in qryCombined )
{
object mergeObject;
string commaPersonIds = combinedFamilyItem.Persons.Select( a => a.Id ).Distinct().ToList().AsDelimited( "," );
var primaryGroupPerson = combinedFamilyItem.Persons.FirstOrDefault() as Person;
if ( mergeObjectsDictionary.ContainsKey( primaryGroupPerson.Id ) )
{
foreach ( var person in combinedFamilyItem.Persons )
{
if ( !mergeObjectsDictionary.ContainsKey( person.Id ) )
{
primaryGroupPerson = person as Person;
break;
}
}
}
// if we are combining from a GroupMemberEntityType list add the GroupMember attributes of the primary person in the combined list
if ( isGroupMemberEntityType )
{
var groupMember = qryEntity.OfType<GroupMember>().Where( a => a.PersonId == primaryGroupPerson.Id ).FirstOrDefault();
primaryGroupPerson.AdditionalLavaFields = primaryGroupPerson.AdditionalLavaFields ?? new Dictionary<string, object>();
if ( groupMember != null )
{
primaryGroupPerson.AdditionalLavaFields.Add( "GroupMember", groupMember );
}
}
if ( combinedFamilyItem.Persons.Count() > 1 )
{
var combinedPerson = primaryGroupPerson.ToJson().FromJsonOrNull<MergeTemplateCombinedPerson>();
var familyTitle = RockUdfHelper.ufnCrm_GetFamilyTitle( rockContext, null, combinedFamilyItem.GroupId, commaPersonIds, true );
combinedPerson.FullName = familyTitle;
var firstNameList = combinedFamilyItem.Persons.Select( a => ( a as Person ).FirstName ).ToList();
var nickNameList = combinedFamilyItem.Persons.Select( a => ( a as Person ).NickName ).ToList();
combinedPerson.FirstName = firstNameList.AsDelimited( ", ", " & " );
combinedPerson.NickName = nickNameList.AsDelimited( ", ", " & " );
combinedPerson.LastName = primaryGroupPerson.LastName;
combinedPerson.SuffixValueId = null;
combinedPerson.SuffixValue = null;
mergeObject = combinedPerson;
}
else
{
mergeObject = primaryGroupPerson;
}
mergeObjectsDictionary.AddOrIgnore( primaryGroupPerson.Id, mergeObject );
}
}
else if ( isGroupMemberEntityType )
{
foreach ( var groupMember in qryEntity.AsNoTracking().OfType<GroupMember>() )
{
var person = groupMember.Person;
person.AdditionalLavaFields = new Dictionary<string, object>();
person.AdditionalLavaFields.Add( "GroupMember", groupMember );
mergeObjectsDictionary.AddOrIgnore( groupMember.PersonId, person );
}
}
else
{
foreach ( var item in qryEntity.AsNoTracking() )
{
mergeObjectsDictionary.AddOrIgnore( item.Id, item );
}
}
}
var entitySetItemService = new EntitySetItemService( rockContext );
string[] emptyJson = new string[] { string.Empty, "{}" };
var entitySetItemMergeValuesQry = entitySetItemService.GetByEntitySetId( entitySetId, true ).Where( a => !emptyJson.Contains( a.AdditionalMergeValuesJson ) );
if ( fetchCount.HasValue )
{
entitySetItemMergeValuesQry = entitySetItemMergeValuesQry.Take( fetchCount.Value );
}
// the entityId to use for NonEntity objects
int nonEntityId = 1;
// now, add the additional MergeValues regardless of if the EntitySet contains IEntity items or just Non-IEntity items
foreach ( var additionalMergeValuesItem in entitySetItemMergeValuesQry.AsNoTracking() )
{
object mergeObject;
int entityId;
if ( additionalMergeValuesItem.EntityId > 0 )
{
entityId = additionalMergeValuesItem.EntityId;
}
else
{
// not pointing to an actual EntityId, so use the nonEntityId for ti
entityId = nonEntityId++;
}
if ( mergeObjectsDictionary.ContainsKey( entityId ) )
{
mergeObject = mergeObjectsDictionary[entityId];
}
else
{
if ( entitySet.EntityTypeId.HasValue )
{
// if already have real entities in our list, don't add additional items to the mergeObjectsDictionary
continue;
}
// non-Entity merge object, so just use Dictionary
mergeObject = new Dictionary<string, object>();
mergeObjectsDictionary.AddOrIgnore( entityId, mergeObject );
}
foreach ( var additionalMergeValue in additionalMergeValuesItem.AdditionalMergeValues )
{
if ( mergeObject is IEntity )
{
// add the additional fields to AdditionalLavaFields
IEntity mergeEntity = ( mergeObject as IEntity );
mergeEntity.AdditionalLavaFields = mergeEntity.AdditionalLavaFields ?? new Dictionary<string, object>();
object mergeValueObject = additionalMergeValue.Value;
mergeEntity.AdditionalLavaFields.AddOrIgnore( additionalMergeValue.Key, mergeValueObject );
}
else if ( mergeObject is IDictionary<string, object> )
{
// anonymous object with no fields yet
IDictionary<string, object> nonEntityObject = mergeObject as IDictionary<string, object>;
nonEntityObject.AddOrIgnore( additionalMergeValue.Key, additionalMergeValue.Value );
}
else
{
throw new Exception( string.Format( "Unexpected MergeObject Type: {0}", mergeObject ) );
}
}
}
var result = mergeObjectsDictionary.Select( a => a.Value );
if ( fetchCount.HasValue )
{
// make sure the result is limited to fetchCount (even though the above queries are also limited to fetch count)
result = result.Take( fetchCount.Value );
}
return result.ToList();
}