/// <summary>
		/// Creates the given index <paramref name="definition"/>.
		/// </summary>
		/// <param name="definition">The <see cref="IndexDefinition"/>.</param>
		private void CreateIndex(IndexDefinition definition)
		{
			new Action(() => {
				// delete the index if it exists
				if (connectionManager.Head(definition.Name, new[] {HttpStatusCode.OK, HttpStatusCode.NotFound}).StatusCode == HttpStatusCode.OK)
					connectionManager.Delete(definition.Name);

				// create the index
				connectionManager.Put(definition.Name, definition);
			}).Retry(new FixedIntervalStrategy(3, TimeSpan.FromMilliseconds(100)));
		}
		/// <summary>
		/// Creates a <see cref="IndexDescriptor"/> from this descriptor.
		/// </summary>
		/// <param name="context">The <see cref="IMansionContext"/>.</param>
		/// <returns>The created <see cref="IndexDefinition"/>.</returns>
		public IndexDefinition CreateDefinition(IMansionContext context)
		{
			// validate arguments
			if (context == null)
				throw new ArgumentNullException("context");

			// get the required properties
			var name = Properties.Get<string>(context, "name");

			// create the definition
			var definition = new IndexDefinition(name);

			// map settings
			int numberOfShards;
			if (Properties.TryGet(context, "numberOfShards", out numberOfShards))
				definition.Settings.NumberOfShards = numberOfShards;
			int numberOfReplicas;
			if (Properties.TryGet(context, "numberOfReplicas", out numberOfReplicas))
				definition.Settings.NumberOfReplicas = numberOfReplicas;

			// return the created definition
			return definition;
		}
		/// <summary>
		/// Optimizes the indexes as defined by <paramref name="definition"/> within the given ElasticSearch instance.
		/// </summary>
		/// <param name="context">The <see cref="IMansionContext"/>.</param>
		/// <param name="definition">The <see cref="IndexDefinition"/> which to optimize.</param>
		public void Optimize(IMansionContext context, IndexDefinition definition)
		{
			// validate arguments
			if (context == null)
				throw new ArgumentNullException("context");
			if (definition == null)
				throw new ArgumentNullException("definition");

			// format the resource
			var resource = definition.Name + "/_optimize";

			// execute the request
			new Action(() => connectionManager.Post(resource)).Retry(new FixedIntervalStrategy(3, TimeSpan.FromMilliseconds(100)));
		}
		/// <summary>
		/// Maps all the analysis components from <paramref name="type"/> to <paramref name="definition"/>.
		/// </summary>
		/// <param name="context">The <see cref="IMansionContext"/>.</param>
		/// <param name="type">The <see cref="IDescriptee"/>.</param>
		/// <param name="definition">The <see cref="IndexDefinition"/>.</param>
		private static void MapAnalysisComponents(IMansionContext context, IDescriptee type, IndexDefinition definition)
		{
			// map all the analysis components
			definition.Settings.AnalysisSettings.Add(type.GetDescriptors<BaseAnalysisDescriptor<BaseAnalyzer>>().Select(descriptor => descriptor.Create(context)));
			definition.Settings.AnalysisSettings.Add(type.GetDescriptors<BaseAnalysisDescriptor<BaseCharFilter>>().Select(descriptor => descriptor.Create(context)));
			definition.Settings.AnalysisSettings.Add(type.GetDescriptors<BaseAnalysisDescriptor<BaseTokenFilter>>().Select(descriptor => descriptor.Create(context)));
			definition.Settings.AnalysisSettings.Add(type.GetDescriptors<BaseAnalysisDescriptor<BaseTokenizer>>().Select(descriptor => descriptor.Create(context)));
		}
		/// <summary>
		/// Maps the given <paramref name="type"/> in <paramref name="typeMapping"/>.
		/// </summary>
		/// <param name="context">The <see cref="IMansionContext"/>.</param>
		/// <param name="definition">The <see cref="IndexDefinition"/>.</param>
		/// <param name="type">The <see cref="ITypeDefinition"/>.</param>
		/// <param name="typeMapping">The <see cref="TypeMapping"/>.</param>
		private static void MapType(IMansionContext context, IndexDefinition definition, ITypeDefinition type, TypeMapping typeMapping)
		{
			// map the type descriptor, if any
			TypeMapping.TypeMappingDescriptor descriptor;
			if (type.TryGetDescriptor(out descriptor))
				descriptor.UpdateMapping(context, typeMapping);

			// map all the properties of this type
			MapProperties(context, type, typeMapping);

			// map all the analysis components defined on this type
			MapAnalysisComponents(context, type, definition);

			// loop over all the children of this type
			foreach (var childType in type.GetChildTypes(context))
			{
				// clone the parent mapping, children should include the properties of the parent
				var childMapping = typeMapping.Clone(childType);

				// map the the child
				MapType(context, definition, childType, childMapping);
			}

			// append the mapping to the index definition
			definition.Add(typeMapping);
		}
		/// <summary>
		/// Creates the type mapping for the given <paramref name="type"/>.
		/// </summary>
		/// <param name="context">The <see cref="IMansionContext"/>.</param>
		/// <param name="definition">The <see cref="IndexDefinition"/>.</param>
		/// <param name="type">The <see cref="ITypeDefinition"/>.</param>
		private static void CreateTypeMapping(IMansionContext context, IndexDefinition definition, ITypeDefinition type)
		{
			// create the type mapping
			var typeMapping = new TypeMapping(type);

			// map the type
			MapType(context, definition, type, typeMapping);
		}