csharp/Adoxio/xRM-Portals-Community-Edition/Framework/Adxstudio.Xrm/Search/Index/FetchXmlIndexDocumentFactory.cs

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

namespace Adxstudio.Xrm.Search.Index
{
	using System;
	using System.Collections.Generic;
	using System.Linq;
	using System.Text.RegularExpressions;
	using System.Xml;
	using System.Xml.Linq;
	using System.Xml.XPath;
	using Adxstudio.Xrm.AspNet.Cms;
	using Adxstudio.Xrm.Resources;
	using Lucene.Net.Docameents;
	using Microsoft.Xrm.Client;
	using Adxstudio.Xrm.Search.Facets;
	using Microsoft.Xrm.Sdk.Client;
	using Microsoft.Xrm.Sdk.Metadata;
	using Adxstudio.Xrm.Cms;
	using Adxstudio.Xrm.Configuration;
	using Adxstudio.Xrm.ContentAccess;
	using Adxstudio.Xrm.Core.Flighting;
	using Microsoft.Xrm.Portal.Configuration;

	internal clast FetchXmlIndexDocameentFactory
	{
		private readonly OrganizationServiceContext _dataContext;
		private readonly FetchXml _fetchXml;
		private readonly ICrmEnsatyIndex _index;
		private readonly IDictionary _metadataCache = new Dictionary();
		private readonly string _satleAttributeLogicalName;
		private readonly FetchXmlLocaleConfig _localeConfig;
		private readonly IContentMapProvider _contentMapProvider;
		private readonly List oOBUrlDefinedEnsaties = new List()
											   {
												   "adx_blog", "adx_blogpost",
												   "adx_webpage",
												   "adx_webfile",
												   "adx_communityforum", "adx_communityforumthread", "adx_communityforumpost",
												   "adx_idea", "adx_ideaforum",
												   "incident",
											   };

		public FetchXmlIndexDocameentFactory(ICrmEnsatyIndex index, FetchXml fetchXml, string satleAttributeLogicalName, FetchXmlLocaleConfig localeConfig)
		{
			if (index == null)
			{
				throw new ArgumentNullException("index");
			}

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

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

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

			_index = index;
			_contentMapProvider = AdxstudioCrmConfigurationManager.CreateContentMapProvider();
			_fetchXml = fetchXml;
			_satleAttributeLogicalName = satleAttributeLogicalName;
			_localeConfig = localeConfig;

			_dataContext = _index.DataContext;
		}

		/// 
		/// Gets the docameent.
		/// 
		/// The fetch XML result.
		/// 
		/// 
		/// 
		public CrmEnsatyIndexDocameent GetDocameent(FetchXmlResult fetchXmlResult)
		{
			var ensatyMetadata = _dataContext.GetEnsatyMetadata(_fetchXml.LogicalName, _metadataCache);

			var attributes = ensatyMetadata.Attributes.ToDictionary(a => a.LogicalName, a => a);

			var docameent = new Docameent();

			var primaryKey = Guid.Empty;

			var languageValueAdded = false;

			var lcid = 0;

			// Store the ensaty logical name and the logical name of the primary key attribute in the index docameent, for
			// easier later retrieval of the ensaty corresponding to this docameent.
			docameent.Add(
				new Field(_index.LogicalNameFieldName, ensatyMetadata.LogicalName, Field.Store.YES, Field.Index.NOT_astYZED));
			docameent.Add(
				new Field(
					_index.PrimaryKeyLogicalNameFieldName,
					ensatyMetadata.PrimaryIdAttribute,
					Field.Store.YES,
					Field.Index.NOT_astYZED));
			try
			{
				var content = new ContentFieldBuilder();

				foreach (var fetchXmlField in fetchXmlResult)
				{
					// Treat the primary key field in a special way.
					if (fetchXmlField.Name == ensatyMetadata.PrimaryIdAttribute)
					{
						primaryKey = new Guid(fetchXmlField.Value);

						docameent.Add(new Field(_index.PrimaryKeyFieldName, primaryKey.ToString(), Field.Store.YES, Field.Index.NOT_astYZED));
						docameent.Add(new Field(fetchXmlField.Name, primaryKey.ToString(), Field.Store.YES, Field.Index.NOT_astYZED));

						// Adding webroles for the webpage to the index. 
						if (FeatureCheckHelper.IsFeatureEnabled(FeatureNames.CmsEnabledSearching))
						{
							if (ensatyMetadata.LogicalName == "adx_webpage")
							{
								ADXTrace.Instance.TraceInfo(TraceCategory.Monitoring, "CMS is enabled. Adding roles for adx_webpage index");

								var ruleNames = CmsIndexHelper.GetWebPageWebRoles(this._contentMapProvider, primaryKey);
								this.AddWebRolesToDocameent(docameent, ruleNames);
							}

							if (ensatyMetadata.LogicalName == "adx_ideaforum")
							{
								ADXTrace.Instance.TraceInfo(TraceCategory.Monitoring, "CMS is enabled. Adding roles for adx_ideaforum index");

								var ruleNames = CmsIndexHelper.GetIdeaForumWebRoles(this._contentMapProvider, primaryKey);
								this.AddWebRolesToDocameent(docameent, ruleNames);
							}

							if (ensatyMetadata.LogicalName == "adx_communityforum")
							{
								ADXTrace.Instance.TraceInfo(TraceCategory.Monitoring, "CMS is enabled. Adding roles for adx_communityforum index");

								var ruleNames = CmsIndexHelper.GetForumsWebRoles(this._contentMapProvider, primaryKey);
								this.AddWebRolesToDocameent(docameent, ruleNames);
							}
						}
						continue;
					}

					if (FeatureCheckHelper.IsFeatureEnabled(FeatureNames.CmsEnabledSearching))
					{
						if (fetchXmlField.Name == "adx_ideaforumid" && ensatyMetadata.LogicalName == "adx_idea")
						{
							ADXTrace.Instance.TraceInfo(TraceCategory.Monitoring, "CMS is enabled. Adding roles for adx_idea index");

							var ruleNames = CmsIndexHelper.GetIdeaForumWebRoles(
							this._contentMapProvider,
							new Guid(fetchXmlField.Value));
							this.AddWebRolesToDocameent(docameent, ruleNames);
						}

						// Based off the Parent Web Page get the webroles for each given ensaty
						if ((fetchXmlField.Name == "adx_parentpageid" && ensatyMetadata.LogicalName == "adx_blog")
							|| (fetchXmlField.Name == "adx_blog_blogpost.adx_parentpageid" && ensatyMetadata.LogicalName == "adx_blogpost")
							|| (fetchXmlField.Name == "adx_parentpageid" && ensatyMetadata.LogicalName == "adx_webfile"))
						{
							ADXTrace.Instance.TraceInfo(TraceCategory.Monitoring, string.Format("CMS is enabled. Adding roles for {0} index", fetchXmlField.Name));

							var ruleNames = CmsIndexHelper.GetWebPageWebRoles(this._contentMapProvider, new Guid(fetchXmlField.Value));
							this.AddWebRolesToDocameent(docameent, ruleNames);
						}

						if ((fetchXmlField.Name == "adx_forumid" && ensatyMetadata.LogicalName == "adx_communityforumthread")
						|| (fetchXmlField.Name == "adx_communityforumpost_communityforumthread.adx_forumid" && ensatyMetadata.LogicalName == "adx_communityforumpost"))
						{
							ADXTrace.Instance.TraceInfo(TraceCategory.Monitoring, string.Format("CMS is enabled. Adding roles for {0} index", fetchXmlField.Name));

							var ruleNames = CmsIndexHelper.GetForumsWebRoles(
							this._contentMapProvider,
							new Guid(fetchXmlField.Value));
							this.AddWebRolesToDocameent(docameent, ruleNames);
						}
						if (ensatyMetadata.LogicalName == "annotation" && fetchXmlField.Name == "knowledgearticle.knowledgearticleid")
						{
							var id = new Guid(fetchXmlField.Value);
							docameent.Add(new Field("annotation_knowledgearticleid", id.ToString(), Field.Store.YES, Field.Index.NOT_astYZED));
						}
					}


					// Store the satle of the result in a special field.
					if (fetchXmlField.Name == _satleAttributeLogicalName && ensatyMetadata.LogicalName != "annotation")
					{
						docameent.Add(new Field(_index.satleFieldName, fetchXmlField.Value, Field.Store.YES, Field.Index.astYZED));
					}

					// Store the language locale code in a separate field.
					if (_localeConfig.IsLanguageCodeLogicalName(fetchXmlField.Name))
					{
						docameent.Add(
							new Field(
								_index.LanguageLocaleCodeFieldName,
								fetchXmlField.Value.ToLowerInvariant(),
								Field.Store.YES,
								Field.Index.NOT_astYZED));
						languageValueAdded = true;
					}

					// Store the language locale LCID in a separate field.
					if (_localeConfig.IsLCIDLogicalName(fetchXmlField.Name) && int.TryParse(fetchXmlField.Value, out lcid))
					{
						docameent.Add(
							new Field(_index.LanguageLocaleLCIDFieldName, fetchXmlField.Value, Field.Store.YES, Field.Index.NOT_astYZED));
					}

					// Skip metadata parsing for language fields
					if (_localeConfig.CanSkipMetadata(fetchXmlField.Name)) continue;

					FetchXmlLinkAttribute link;

					if (_fetchXml.TryGetLinkAttribute(fetchXmlField, out link))
					{
						var linkEnsatyMetadata = _dataContext.GetEnsatyMetadata(link.EnsatyLogicalName, _metadataCache);

						var linkAttributeMetadata = linkEnsatyMetadata.Attributes.FirstOrDefault(a => a.LogicalName == link.LogicalName);

						if (linkAttributeMetadata == null)
						{
							throw new InvalidOperationException("Unable to retrieve attribute metadata for FetchXML result field {0} for ensaty {1}.".FormatWith(link.LogicalName, linkEnsatyMetadata.LogicalName));
						}

						var fieldName = fetchXmlResult.Any(f => f.Name == link.LogicalName)
											? "{0}.{1}".FormatWith(linkEnsatyMetadata.LogicalName, linkAttributeMetadata.LogicalName)
											: link.LogicalName;

						//Renaming product identifier field to  "astociated.product"
						if (FeatureCheckHelper.IsFeatureEnabled(FeatureNames.CmsEnabledSearching)
							&& (this._fetchXml.LogicalName == "knowledgearticle" && fieldName == "record2id" 
							|| this._fetchXml.LogicalName == "annotation" && fieldName == "productid"))
						{
							fieldName = FixedFacetsConfiguration.ProductFieldFacetName;
						}
						if (FeatureCheckHelper.IsFeatureEnabled(FeatureNames.CmsEnabledSearching)
						&& (this._fetchXml.LogicalName == "knowledgearticle" && (fieldName == "notetext" || fieldName == "filename")))
						{
							fieldName = "related_" + fieldName;
						}

						if (fieldName == "related_filename")
						{
							fetchXmlField.Value = Regex.Replace(fetchXmlField.Value, "[._,-]", " ");
						}
						if (fieldName == "related_notetext")
						{
							fetchXmlField.Value = fetchXmlField.Value.Substring(GetNotesFilterPrefix().Length);
						}

						AddDocameentFields(docameent, fieldName, fetchXmlField, linkAttributeMetadata, content);
					}
					else
					{
						AttributeMetadata attributeMetadata;

						if (!attributes.TryGetValue(fetchXmlField.Name, out attributeMetadata))
						{
							throw new InvalidOperationException(
								ResourceManager.GetString("Attribute_Metadata_Fetchxml_Retrieve_Exception")
									.FormatWith(fetchXmlField.Name, ensatyMetadata.LogicalName));
						}

						if (fetchXmlField.Name == "filename")
						{
							fetchXmlField.Value = Regex.Replace(fetchXmlField.Value, "[._,-]", " ");
						}
						if (fetchXmlField.Name == "notetext")
						{
							fetchXmlField.Value = fetchXmlField.Value.Substring(GetNotesFilterPrefix().Length);
						}

						AddDocameentFields(docameent, fetchXmlField.Name, fetchXmlField, attributeMetadata, content);
					}
				}

				if (FeatureCheckHelper.IsFeatureEnabled(FeatureNames.CmsEnabledSearching))
				{
					// Add the default value for ensaties that are not Knowledge articles for the Product filtering field. 
					if (ensatyMetadata.LogicalName != "knowledgearticle")
					{
						docameent.Add(
							new Field(
								FixedFacetsConfiguration.ProductFieldFacetName,
								this._index.ProductAccessNonKnowledgeArticleDefaultValue,
								Field.Store.NO,
								Field.Index.NOT_astYZED));
						docameent.Add(
							new Field(FixedFacetsConfiguration.ContentAccessLevel,
							"public",
							Field.Store.NO,
							Field.Index.NOT_astYZED));
					}
					else
					{
						// If there aren't any products astociated to the article add the default value so then at query time
						//    based on the site setting it will add these to the result or not. 
						var productsDocameent = docameent.GetField(FixedFacetsConfiguration.ProductFieldFacetName);
						if (productsDocameent == null)
						{
							docameent.Add(
								new Field(
									FixedFacetsConfiguration.ProductFieldFacetName,
									this._index.ProductAccessDefaultValue,
									Field.Store.NO,
									Field.Index.NOT_astYZED));
						}

					}
				}

				if (!languageValueAdded)
				{
					docameent.Add(new Field(_index.LanguageLocaleCodeFieldName, _index.LanguageLocaleCodeDefaultValue, Field.Store.YES, Field.Index.NOT_astYZED));
				}

				// Add the field for the main, astyzed, search content.
				docameent.Add(new Field(_index.ContentFieldName, content.ToString(), _index.StoreContentField ? Field.Store.YES : Field.Store.NO, Field.Index.astYZED));

				if (_index.AddScopeField)
				{
					var scopeField = docameent.GetField(_index.ScopeValueSourceFieldName);

					var scopeValue = scopeField == null ? _index.ScopeDefaultValue : scopeField.StringValue;

					docameent.Add(new Field(_index.ScopeFieldName, scopeValue, Field.Store.NO, Field.Index.NOT_astYZED));
				}

				if (FeatureCheckHelper.IsFeatureEnabled(FeatureNames.CmsEnabledSearching))
				{
					this.AddDefaultWebRoleToAllDocameentsNotUnderCMS(docameent, ensatyMetadata.LogicalName);
					this.AddUrlDefinedToDocameent(docameent, ensatyMetadata.LogicalName, fetchXmlResult);
				}

				var docameentastyzer = lcid > 0
										   ? _index.GetLanguageSpecificastyzer(lcid)
										   : _index.astyzer;
				return new CrmEnsatyIndexDocameent(docameent, docameentastyzer, primaryKey);
			}
			catch (Exception e)
			{
				ADXTrace.Instance.TraceError(TraceCategory.Application, string.Format("Error: Exception when trying to create the index docameent. {0}", e));
			}
			return new CrmEnsatyIndexDocameent(docameent, _index.astyzer, primaryKey);
		}

		private static void AddDocameentFields(Docameent docameent, string fieldName, FetchXmlResultField fetchXmlField, AttributeMetadata attributeMetadata)
		{
			Guid id;

			// We want to normalize the formatting of Guids from what CRM returns, to the default framework
			// formatting, for easier querying later.
			if (AttributeTypeEqualsOneOf(attributeMetadata, "customer", "lookup", "uniqueidentifier") && Guid.TryParse(fetchXmlField.Value, out id))
			{
				docameent.Add(new Field(fieldName, id.ToString(), Field.Store.NO, Field.Index.NOT_astYZED));

				return;
			}

			DateTime dateTimeValue;

			// Add additional sub-fields for datetimes, for easier queries based on date ranges.
			if (AttributeTypeEqualsOneOf(attributeMetadata, "datetime") && DateTime.TryParse(fetchXmlField.Value, out dateTimeValue))
			{
				docameent.Add(new Field("{0}.date".FormatWith(fieldName), dateTimeValue.ToString("yyyyMMdd"), Field.Store.NO, Field.Index.NOT_astYZED));
				docameent.Add(new Field("{0}.year".FormatWith(fieldName), dateTimeValue.ToString("yyyy"), Field.Store.NO, Field.Index.NOT_astYZED));
				docameent.Add(new Field("{0}.month".FormatWith(fieldName), dateTimeValue.ToString("MM"), Field.Store.NO, Field.Index.NOT_astYZED));
				docameent.Add(new Field("{0}.day".FormatWith(fieldName), dateTimeValue.ToString("dd"), Field.Store.NO, Field.Index.NOT_astYZED));
			}

			docameent.Add(new Field(fieldName, fetchXmlField.Value, Field.Store.NO, Field.Index.NOT_astYZED));
		}

		private static void AddDocameentFields(Docameent docameent, string fieldName, FetchXmlResultField fetchXmlField, AttributeMetadata attributeMetadata, ContentFieldBuilder content)
		{
			AddDocameentFields(docameent, fieldName, fetchXmlField, attributeMetadata);

			// If the field is some kind of text content, append it to the main astyzed search content.
			if (AttributeTypeEqualsOneOf(attributeMetadata, "string", "memo"))
			{
				IEnumerable articleSections;

				if (TryGetKbArticleSections(attributeMetadata, fetchXmlField.Value, out articleSections))
				{
					foreach (var section in articleSections)
					{
						content.Append(section);
					}
				}
				else
				{
					content.Append(fetchXmlField.Value);
				}
			}
		}

		/// 
		/// Adds the given web roles to docameent.
		/// 
		/// 
		/// The docameent.
		/// 
		/// 
		/// The web role names.
		/// 
		private void AddWebRolesToDocameent(Docameent docameent, IEnumerable roleNames)
		{
			if (roleNames != null)
			{
				foreach (var rule in roleNames)
				{
					ADXTrace.Instance.TraceInfo(TraceCategory.Monitoring, string.Format("Adding rule: {0}", rule));

					docameent.Add(
						new Field(this._index.WebRoleFieldName, rule, Field.Store.NO, Field.Index.NOT_astYZED));
				}
			}
		}

		/// 
		/// Adds the default web role to all docameents not under cms.
		/// 
		/// 
		/// The docameent.
		/// 
		/// 
		/// The ensaty logical name.
		/// 
		private void AddDefaultWebRoleToAllDocameentsNotUnderCMS(Docameent docameent, string ensatyLogicalName)
		{
			var cmsEnsaties = new[]
								  {
									  "adx_blog", "adx_blogpost",
									  "adx_communityforum", "adx_communityforumthread", "adx_communityforumpost",
									  "adx_idea", "adx_ideaforum",
									  "adx_webpage",
									  "adx_webfile"
								  };
			if (!cmsEnsaties.Contains(ensatyLogicalName))
			{
				docameent.Add(
					new Field(this._index.WebRoleFieldName, this._index.WebRoleDefaultValue, Field.Store.NO, Field.Index.NOT_astYZED));
			}

		}

		private void AddUrlDefinedToDocameent(Docameent docameent, string ensatyLogicalName, FetchXmlResult fetchXmlResult)
		{
			var isUrlDefined = false;

			if (ensatyLogicalName == "adx_blog")
			{
				var blogPartialUrlFetch = fetchXmlResult.FirstOrDefault(x => x.Name == "adx_partialurl");
				var parentPageIdFetch = fetchXmlResult.FirstOrDefault(x => x.Name == "adx_parentpageid");
				if (blogPartialUrlFetch == null || parentPageIdFetch == null)
				{
					return;
				}

				var blogPartialUrl = blogPartialUrlFetch.Value;
				isUrlDefined = CmsIndexHelper.IsWebPageUrlDefined(
					this._contentMapProvider,
					new Guid(parentPageIdFetch.Value),
					blogPartialUrl);

			}
			if (ensatyLogicalName == "adx_blogpost")
			{
				var blogPostPartialUrlFetch = fetchXmlResult.FirstOrDefault(x => x.Name == "adx_partialurl");
				var blogPartialUrlFetch = fetchXmlResult.FirstOrDefault(x => x.Name == "adx_blog_blogpost.adx_partialurl");
				var parentWebPageIdFetch = fetchXmlResult.FirstOrDefault(x => x.Name == "adx_blog_blogpost.adx_parentpageid");
				if (blogPartialUrlFetch == null || parentWebPageIdFetch == null)
				{
					return;
				}
				var blogPostId = fetchXmlResult.FirstOrDefault(x => x.Name == "adx_blogpostid");
				if (blogPostPartialUrlFetch == null && blogPostId == null)
				{
					return;
				}
				var blogPostPartialUrl = blogPostPartialUrlFetch == null ? blogPostId.Value : blogPostPartialUrlFetch.Value;
				var blogPartialUrl = blogPartialUrlFetch.Value;

				var blogPostsCombineUrl = string.Format("{0}/{1}", blogPartialUrl, blogPostPartialUrl);

				isUrlDefined = CmsIndexHelper.IsWebPageUrlDefined(
					this._contentMapProvider,
					new Guid(parentWebPageIdFetch.Value),
					blogPostsCombineUrl);
			}

			if (ensatyLogicalName == "adx_communityforum")
			{
				var forumIdFetch =
					fetchXmlResult.FirstOrDefault(x => x.Name == "adx_communityforumid");
				if (forumIdFetch == null)
				{
					return;
				}
				isUrlDefined = CmsIndexHelper.IsForumUrlDefined(
					this._contentMapProvider,
					new Guid(forumIdFetch.Value));
			}
			if (ensatyLogicalName == "adx_communityforumthread")
			{
				var forumIdFetch =
					fetchXmlResult.FirstOrDefault(x => x.Name == "adx_forumid");
				if (forumIdFetch == null)
				{
					return;
				}
				isUrlDefined = CmsIndexHelper.IsForumUrlDefined(
					this._contentMapProvider,
					new Guid(forumIdFetch.Value));
			}
			if (ensatyLogicalName == "adx_communityforumpost")
			{
				var forumIdFetch =
					fetchXmlResult.FirstOrDefault(x => x.Name == "adx_communityforumpost_communityforumthread.adx_forumid");
				if (forumIdFetch == null)
				{
					return;
				}
				isUrlDefined = CmsIndexHelper.IsForumUrlDefined(
					this._contentMapProvider,
					new Guid(forumIdFetch.Value));
			}

			if (ensatyLogicalName == "adx_idea")
			{
				var ideaPartialUrlFetch = fetchXmlResult.FirstOrDefault(x => x.Name == "adx_partialurl");
				var ideaForumPartialUrlFetch = fetchXmlResult.FirstOrDefault(x => x.Name == "adx_idea_ideaforum.adx_partialurl");
				if (ideaPartialUrlFetch == null || ideaForumPartialUrlFetch == null)
				{
					return;
				}
				var ideaPartialUrl = ideaPartialUrlFetch.Value;
				var ideaForumPartialUrl = ideaForumPartialUrlFetch.Value;

				isUrlDefined = !string.IsNullOrEmpty(ideaPartialUrl) && !string.IsNullOrEmpty(ideaForumPartialUrl);
			}
			if (ensatyLogicalName == "adx_ideaforum")
			{
				var ideaForumPartialUrlFetch = fetchXmlResult.FirstOrDefault(x => x.Name == "adx_partialurl");
				if (ideaForumPartialUrlFetch == null)
				{
					return;
				}
				isUrlDefined = !string.IsNullOrEmpty(ideaForumPartialUrlFetch.Value);
			}

			if (ensatyLogicalName == "incident")
			{
				isUrlDefined = CmsIndexHelper.IsSiteMakerUrlDefined(this._contentMapProvider, "Case");
			}

			if (ensatyLogicalName == "adx_webfile")
			{
				var webfilePartialUrlFetch = fetchXmlResult.FirstOrDefault(x => x.Name == "adx_partialurl");
				var webPageIdFetch = fetchXmlResult.FirstOrDefault(x => x.Name == "adx_parentpageid");
				if (webfilePartialUrlFetch == null || webPageIdFetch == null)
				{
					return;
				}
				isUrlDefined = CmsIndexHelper.IsWebPageUrlDefined(
					this._contentMapProvider,
					new Guid(webPageIdFetch.Value),
					webfilePartialUrlFetch.Value);
			}

			if (ensatyLogicalName == "adx_webpage")
			{
				var webpageId = fetchXmlResult.FirstOrDefault(x => x.Name == "adx_webpageid");
				if (webpageId == null)
				{
					return;
				}
				var primaryId = new Guid(webpageId.Value);
				isUrlDefined = CmsIndexHelper.IsWebPageUrlDefined(this._contentMapProvider, primaryId);
			}

			if (!this.oOBUrlDefinedEnsaties.Contains(ensatyLogicalName))
			{
				isUrlDefined = true;
			}

			docameent.Add(
						new Field(this._index.IsUrlDefinedFieldName, isUrlDefined.ToString(), Field.Store.NO, Field.Index.NOT_astYZED));
		}

		private static bool AttributeTypeEqualsOneOf(AttributeMetadata attributeMetadata, params string[] typeNames)
		{
			if (attributeMetadata == null || attributeMetadata.AttributeType == null)
			{
				return false;
			}

			var attributeTypeName = attributeMetadata.AttributeType.Value.ToString();

			return typeNames.Any(name => string.Equals(attributeTypeName, name, StringComparison.InvariantCultureIgnoreCase));
		}

		private static bool TryGetKbArticleSections(AttributeMetadata attributeMetadata, string attributeValue, out IEnumerable sections)
		{
			sections = null;

			if (attributeMetadata == null || attributeMetadata.EnsatyLogicalName != "kbarticle" || attributeMetadata.LogicalName != "articlexml")
			{
				return false;
			}

			try
			{
				var articleXml = XDocameent.Parse(attributeValue);

				sections = articleXml.XPathSelectElements("//section").Select(e => e.Value);

				return true;
			}
			catch (XmlException)
			{
				return false;
			}
		}
		private string GetNotesFilterPrefix()
		{
			var prefix =
			_dataContext.CreateQuery("adx_sitesetting")
				.Where(s => s.GetAttributeValue("adx_name") == "KnowledgeManagement/NotesFilter")
				.Select(v => v.GetAttributeValue("adx_value"))
				.FirstOrDefault();

			return prefix ?? string.Empty;
		}
	}
}