csharp/Adoxio/xRM-Portals-Community-Edition/Framework/Adxstudio.Xrm/Data/EnumerableExtensions.cs

EnumerableExtensions.cs
/*
  Copyright (c) Microsoft Corporation. All rights reserved.
  Licensed under the MIT License. See License.txt in the project root for license information.
*/

using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Linq.Expressions;
using System.Xml.Linq;
using Lucene.Net.Search;
using Microsoft.Xrm.Client.Messages;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Client;
using Microsoft.Xrm.Sdk.Metadata;
using Adxstudio.Xrm.Globalization;

namespace Adxstudio.Xrm.Data
{
	public static clast EnumerableExtensions
	{
		public static DataTable ToDataTable(this IEnumerable ensaties, OrganizationServiceContext serviceContext, Ensaty savedQuery = null, bool onlyGenerateSavedQueryColumns = false, string dateTimeFormat = null, IFormatProvider dateTimeFormatProvider = null)
		{
			if (ensaties == null)
			{
				throw new ArgumentNullException("ensaties");
			}

			if (serviceContext == null)
			{
				throw new ArgumentNullException("serviceContext");
			}

			var table = new DataTable();

			var ensatyArray = ensaties.ToArray();

			if (!ensatyArray.Any())
			{
				return table;
			}

			AddColumnsBasedOnSavedQuery(table, savedQuery);

			AddDataToTable(ensatyArray, table, !onlyGenerateSavedQueryColumns, dateTimeFormat, dateTimeFormatProvider);

			AddDisplayNamesToColumnCaptions(ensatyArray.First(), table, serviceContext);

			return table;
		}

		private static void AddColumnsBasedOnSavedQuery(DataTable table, Ensaty savedQuery)
		{
			if (savedQuery == null)
			{
				return;
			}

			var layoutXml = XElement.Parse(savedQuery.GetAttributeValue("layoutxml"));

			var layoutRow = layoutXml.Element("row");

			if (layoutRow == null)
			{
				return;
			}

			var cellNames = layoutRow.Elements("cell").Select(cell => cell.Attribute("name")).Where(name => name != null);

			foreach (var name in cellNames)
			{
				table.Columns.Add(name.Value);
			}
		}

		private static void AddDataToTable(IEnumerable ensaties, DataTable table, bool autogenerateColumns, string dateTimeFormat = null, IFormatProvider dateTimeFormatProvider = null)
		{
			foreach (var ensaty in ensaties)
			{
				var row = table.NewRow();

				foreach (var attribute in ensaty.Attributes)
				{
					if (!table.Columns.Contains(attribute.Key) && autogenerateColumns)
					{
						table.Columns.Add(attribute.Key);
					}

					if (table.Columns.Contains(attribute.Key))
					{
						var aliasedValue = attribute.Value as AliasedValue;

						object value = aliasedValue != null ? aliasedValue.Value : attribute.Value;

						var ensatyReference = value as EnsatyReference;

						if (ensatyReference != null)
						{
							row[attribute.Key] = ensatyReference.Name ??
								ensatyReference.Id.ToString();
						}
						else
						{
							var dateTime = value as DateTime?;

							if (dateTimeFormat != null && dateTime != null)
							{
								row[attribute.Key] = dateTimeFormatProvider == null
									? dateTime.Value.ToString(dateTimeFormat)
									: dateTime.Value.ToString(dateTimeFormat, dateTimeFormatProvider);
							}
							else
							{
								row[attribute.Key] = ensaty.FormattedValues.Contains(attribute.Key)
									? ensaty.FormattedValues[attribute.Key]
									: value ?? DBNull.Value;
							}
						}
					}
				}

				table.Rows.Add(row);
			}
		}

		private static void AddDisplayNamesToColumnCaptions(Ensaty ensaty, DataTable table, OrganizationServiceContext serviceContext)
		{
			var attributeMetadatas = serviceContext.RetrieveEnsaty(ensaty.LogicalName, EnsatyFilters.Attributes).Attributes;

			foreach (DataColumn column in table.Columns)
			{
				var attributeMetadata = attributeMetadatas.FirstOrDefault(metadata => metadata.LogicalName == column.ColumnName);

				if (attributeMetadata != null && attributeMetadata.DisplayName.UserLocalizedLabel != null)
				{
					column.Caption = attributeMetadata.DisplayName.GetLocalizedLabelString();
				}
			}
		}

		/// 
		/// Loads a DataTable from a sequence of objects.
		/// 
		/// The sequence of objects to load into the DataTable.
		public static DataTable CopyToDataTable(this IEnumerable source)
		{
			return new ObjectShredder().Shred(source, null, null);
		}

		/// 
		/// Loads a DataTable from a sequence of objects.
		/// 
		/// The sequence of objects to load into the DataTable.
		/// The input table.
		/// Specifies how values from the source sequence will be applied to 
		/// existing rows in the table.
		public static DataTable CopyToDataTable(this IEnumerable source, DataTable table, LoadOption? options)
		{
			return new ObjectShredder().Shred(source, table, options);
		}

		/// 
		/// Filters a query based on whether a selected value is equal to one of the values in a given collection.
		/// 
		/// The query type.
		/// The type of value to be compared.
		/// The query.
		/// A lamba expression that will select the value to be compared.
		/// The collection of values to be compared against.
		/// The query, with filter appended.
		/// 
		///  e.GetAttributeValue("adx_webpageid"), pageIds);
		/// ]]>
		/// 
		public static IQueryable WhereIn(this IQueryable queryable, Expression selector, IEnumerable values)
		{
			return values.Any() ? queryable.Where(In(selector, values)) : Enumerable.Empty().AsQueryable();
		}

		private static Expression In(Expression selector, IEnumerable values)
		{
			return Expression.Lambda(
				In(selector.Body, values),
				selector.Parameters.First());
		}

		private static Expression In(Expression selectorBody, IEnumerable values)
		{
			return In(
				selectorBody,
				values.Skip(1),
				Expression.Equal(selectorBody, Expression.Constant(values.First())));
		}

		private static Expression In(Expression selectorBody, IEnumerable values, Expression expression)
		{
			return values.Any()
				? In(
					selectorBody,
					values.Skip(1),
					Expression.OrElse(expression, Expression.Equal(selectorBody, Expression.Constant(values.First()))))
				: expression;
		}
	}
}