private void BuildProperty(
            DocumentMapping documentMapping, MemberInfo member, Analyzer parentAnalyzer,
            bool isRoot, string path, BuildContext context
            )
        {
            IFieldBridge bridge = null;

            var analyzer = GetAnalyzer(member) ?? parentAnalyzer;
            var boost    = GetBoost(member);

            var getter = GetGetterFast(documentMapping.MappedClass, member);

            var documentId = mappingDefinition.DocumentId(member);

            if (documentId != null)
            {
                string documentIdName = documentId.Name ?? member.Name;
                bridge = GetFieldBridge(member);

                if (isRoot)
                {
                    if (!(bridge is ITwoWayFieldBridge))
                    {
                        throw new SearchException("Bridge for document id does not implement TwoWayFieldBridge: " + member.Name);
                    }

                    documentMapping.DocumentId = new DocumentIdMapping(
                        documentIdName, member.Name, (ITwoWayFieldBridge)bridge, getter
                        )
                    {
                        Boost = boost
                    };
                }
                else
                {
                    // Components should index their document id
                    documentMapping.Fields.Add(new FieldMapping(
                                                   GetFieldName(member, documentIdName),
                                                   bridge, getter)
                    {
                        Store = Attributes.Store.Yes,
                        Index = Attributes.Index.UnTokenized,
                        Boost = boost
                    });
                }
            }

            var fieldDefinitions = mappingDefinition.FieldDefinitions(member);

            if (fieldDefinitions.Count > 0)
            {
                if (bridge == null)
                {
                    bridge = GetFieldBridge(member);
                }

                foreach (var fieldDefinition in fieldDefinitions)
                {
                    fieldDefinition.Name = fieldDefinition.Name ?? member.Name;
                    var fieldAnalyzer = GetAnalyzerByType(fieldDefinition.Analyzer) ?? analyzer;
                    var field         = new FieldMapping(
                        GetFieldName(member, fieldDefinition.Name),
                        bridge, getter
                        )
                    {
                        Store    = fieldDefinition.Store,
                        Index    = fieldDefinition.Index,
                        Analyzer = fieldAnalyzer,
                        Boost    = boost
                    };

                    documentMapping.Fields.Add(field);
                }
            }

            var embeddedDefinition = mappingDefinition.IndexedEmbedded(member);

            if (embeddedDefinition != null)
            {
                int oldMaxLevel    = maxLevel;
                int potentialLevel = embeddedDefinition.Depth + level;
                if (potentialLevel < 0)
                {
                    potentialLevel = int.MaxValue;
                }

                maxLevel = potentialLevel > maxLevel ? maxLevel : potentialLevel;
                level++;

                System.Type elementType = embeddedDefinition.TargetElement ?? GetMemberTypeOrGenericArguments(member);

                var localPrefix = embeddedDefinition.Prefix == "." ? member.Name + "." : embeddedDefinition.Prefix;

                if (maxLevel == int.MaxValue && context.Processed.Contains(elementType))
                {
                    throw new SearchException(
                              string.Format(
                                  "Circular reference, Duplicate use of {0} in root entity {1}#{2}",
                                  elementType.FullName,
                                  context.Root.MappedClass.FullName,
                                  path + localPrefix));
                }


                if (level <= maxLevel)
                {
                    context.Processed.Add(elementType);                     // push
                    var embedded = new EmbeddedMapping(new DocumentMapping(elementType)
                    {
                        Boost    = GetBoost(member),
                        Analyzer = GetAnalyzer(member) ?? parentAnalyzer
                    }, getter)
                    {
                        Prefix = localPrefix
                    };

                    BuildClass(embedded.Class, false, path + localPrefix, context);

                    /**
                     * We will only index the "expected" type but that's OK, HQL cannot do downcasting either
                     */
                    // ayende: because we have to deal with generic collections here, we aren't
                    // actually using the element type to determine what the value is, since that
                    // was resolved to the element type of the possible collection
                    System.Type actualFieldType = GetMemberTypeOrGenericCollectionType(member);
                    embedded.IsCollection = typeof(IEnumerable).IsAssignableFrom(actualFieldType);

                    documentMapping.Embedded.Add(embedded);
                    context.Processed.Remove(actualFieldType);                     // pop
                }
                else if (logger.IsDebugEnabled)
                {
                    logger.Debug("Depth reached, ignoring " + path + localPrefix);
                }

                level--;
                maxLevel = oldMaxLevel;                 // set back the old max level
            }

            if (mappingDefinition.HasContainedInDefinition(member))
            {
                documentMapping.ContainedIn.Add(new ContainedInMapping(getter));
            }
        }
Ejemplo n.º 2
0
        private void BuildDocumentFieldsForEmbedded(EmbeddedMapping embeddedMapping, object unproxiedInstance, Document doc, string prefix)
        {
            var value = embeddedMapping.Getter.Get(unproxiedInstance);
            if (value == null)
                return;

            try
            {
                prefix += embeddedMapping.Prefix;
                if (value is IDictionary)
                {
                    foreach (object collectionValue in (value as IDictionary).Values)
                    {
                        BuildDocumentFields(collectionValue, doc, embeddedMapping.Class, prefix);
                    }
                }
                else if (value is IEnumerable)
                {
                    foreach (object collectionValue in value as IEnumerable)
                    {
                        BuildDocumentFields(collectionValue, doc, embeddedMapping.Class, prefix);
                    }
                }
                else
                {
                    BuildDocumentFields(value, doc, embeddedMapping.Class, prefix);
                }
            }
            catch (NullReferenceException)
            {
                logger.Error(string.Format("Null reference while processing {0}.{1}, property type {2}",
                                           unproxiedInstance.GetType().FullName,
                                           prefix, value.GetType()));
            }
        }
		private void BuildProperty(
			DocumentMapping documentMapping, MemberInfo member, Analyzer parentAnalyzer,
			bool isRoot, string path, BuildContext context
			)
		{
			IFieldBridge bridge = null;

			var analyzer = GetAnalyzer(member) ?? parentAnalyzer;
			var boost = GetBoost(member);

			var getter = GetGetterFast(documentMapping.MappedClass, member);

			var documentId = mappingDefinition.DocumentId(member);
			if (documentId != null)
			{
				string documentIdName = documentId.Name ?? member.Name;
				bridge = GetFieldBridge(member);

				if (isRoot)
				{
					if (!(bridge is ITwoWayFieldBridge))
					{
						throw new SearchException("Bridge for document id does not implement TwoWayFieldBridge: " + member.Name);
					}

					documentMapping.DocumentId = new DocumentIdMapping(
						documentIdName, member.Name, (ITwoWayFieldBridge)bridge, getter
						) { Boost = boost };
				}
				else
				{
					// Components should index their document id
					documentMapping.Fields.Add(new FieldMapping(
					                           	GetFieldName(member, documentIdName),
					                           	bridge, getter)
					{
						Store = Attributes.Store.Yes,
						Index = Attributes.Index.UnTokenized,
						Boost = boost
					});
				}
			}

			var fieldDefinitions = mappingDefinition.FieldDefinitions(member);
			if (fieldDefinitions.Count > 0)
			{
				if (bridge == null)
					bridge = GetFieldBridge(member);

				foreach (var fieldDefinition in fieldDefinitions)
				{
					fieldDefinition.Name = fieldDefinition.Name ?? member.Name;
					var fieldAnalyzer = GetAnalyzerByType(fieldDefinition.Analyzer) ?? analyzer;
					var field = new FieldMapping(
						GetFieldName(member, fieldDefinition.Name),
						bridge, getter
						)
					{
						Store = fieldDefinition.Store,
						Index = fieldDefinition.Index,
						Analyzer = fieldAnalyzer,
						Boost = boost
					};

					documentMapping.Fields.Add(field);
				}
			}

			var embeddedDefinition = mappingDefinition.IndexedEmbedded(member);
			if (embeddedDefinition != null)
			{
				int oldMaxLevel = maxLevel;
				int potentialLevel = embeddedDefinition.Depth + level;
				if (potentialLevel < 0)
				{
					potentialLevel = int.MaxValue;
				}

				maxLevel = potentialLevel > maxLevel ? maxLevel : potentialLevel;
				level++;

				System.Type elementType = embeddedDefinition.TargetElement ?? GetMemberTypeOrGenericArguments(member);

				var localPrefix = embeddedDefinition.Prefix == "." ? member.Name + "." : embeddedDefinition.Prefix;

				if (maxLevel == int.MaxValue && context.Processed.Contains(elementType))
				{
					throw new SearchException(
						string.Format(
							"Circular reference, Duplicate use of {0} in root entity {1}#{2}",
							elementType.FullName,
							context.Root.MappedClass.FullName,
							path + localPrefix));
				}


				if (level <= maxLevel)
				{
					context.Processed.Add(elementType); // push
					var embedded = new EmbeddedMapping(new DocumentMapping(elementType)
					{
						Boost = GetBoost(member),
						Analyzer = GetAnalyzer(member) ?? parentAnalyzer
					}, getter)
					{
						Prefix = localPrefix
					};

					BuildClass(embedded.Class, false, path + localPrefix, context);

					/**
					 * We will only index the "expected" type but that's OK, HQL cannot do downcasting either
					 */
					// ayende: because we have to deal with generic collections here, we aren't 
					// actually using the element type to determine what the value is, since that 
					// was resolved to the element type of the possible collection
					System.Type actualFieldType = GetMemberTypeOrGenericCollectionType(member);
					embedded.IsCollection = typeof(IEnumerable).IsAssignableFrom(actualFieldType);

					documentMapping.Embedded.Add(embedded);
					context.Processed.Remove(actualFieldType); // pop
				}
				else if (logger.IsDebugEnabled)
				{
					logger.Debug("Depth reached, ignoring " + path + localPrefix);
				}

				level--;
				maxLevel = oldMaxLevel; // set back the old max level
			}

			if (mappingDefinition.HasContainedInDefinition(member))
			{
				documentMapping.ContainedIn.Add(new ContainedInMapping(getter));
			}
		}