private void BuildFilterDefinitions(DocumentMapping classMapping)
		{
			foreach (var filterDef in mappingDefinition.FullTextFilters(classMapping.MappedClass))
			{
				classMapping.FullTextFilterDefinitions.Add(filterDef);
			}
		}
        public EmbeddedMapping(DocumentMapping @class, IGetter getter)
            : base(getter)
        {
            this.Class = @class;
            this.Prefix = string.Empty;

            this.IsCollection = true;
        }
		private void BuildClass(DocumentMapping documentMapping, bool isRoot, string path, BuildContext context)
		{
			IList<System.Type> hierarchy = new List<System.Type>();
			var currClass = documentMapping.MappedClass;

			do
			{
				hierarchy.Add(currClass);
				currClass = currClass.BaseType;
				// NB Java stops at null we stop at object otherwise we process the class twice
				// We also need a null test for things like ISet which have no base class/interface
			} while (currClass != null && currClass != typeof(object));

			for (int index = hierarchy.Count - 1; index >= 0; index--)
			{
				currClass = hierarchy[index];
				/**
				 * Override the default analyzer for the properties if the class hold one
				 * That's the reason we go down the hierarchy
				 */

				// NB Must cast here as we want to look at the type's metadata
				var localAnalyzer = GetAnalyzer(currClass);
				var analyzer = documentMapping.Analyzer ?? localAnalyzer;

				// Check for any ClassBridges
				var classBridges = mappingDefinition.ClassBridges(currClass);
				GetClassBridgeParameters(currClass, classBridges);

				// Now we can process the class bridges
				foreach (var classBridge in classBridges)
				{
					var bridge = BuildClassBridge(classBridge, analyzer);
					documentMapping.ClassBridges.Add(bridge);
				}

				// NB As we are walking the hierarchy only retrieve items at this level
				var propertyInfos = currClass.GetProperties(
					BindingFlags.DeclaredOnly | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance
					);
				foreach (var propertyInfo in propertyInfos)
				{
					BuildProperty(documentMapping, propertyInfo, analyzer, isRoot, path, context);
				}

				var fields = currClass.GetFields(
					BindingFlags.DeclaredOnly | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance
					);
				foreach (var fieldInfo in fields)
				{
					BuildProperty(documentMapping, fieldInfo, analyzer, isRoot, path, context);
				}
			}
		}
Пример #4
0
        public DocumentBuilder(DocumentMapping classMapping, Analyzer defaultAnalyzer, IDirectoryProvider[] directoryProviders,
                               IIndexShardingStrategy shardingStrategy)
        {
            analyzer = new ScopedAnalyzer();
            this.directoryProviders = directoryProviders;
            this.shardingStrategy = shardingStrategy;

            if (classMapping == null) throw new AssertionFailure("Unable to build a DocumemntBuilder with a null class");

            rootClassMapping = classMapping;

            Set<System.Type> processedClasses = new HashedSet<System.Type>();
            processedClasses.Add(classMapping.MappedClass);
            CollectAnalyzers(rootClassMapping, defaultAnalyzer, true, string.Empty, processedClasses);
            //processedClasses.remove( clazz ); for the sake of completness
            analyzer.GlobalAnalyzer = defaultAnalyzer;
            if (idMapping == null)
                throw new SearchException("No document id for: " + classMapping.MappedClass.Name);
        }
		public DocumentMapping Build(System.Type type)
		{
			var documentMapping = new DocumentMapping(type)
			{
				Boost = GetBoost(type),
				IndexName = mappingDefinition.Indexed(type).Index
			};

			var context = new BuildContext
			{
				Root = documentMapping,
				Processed = { type }
			};

			BuildClass(documentMapping, true, string.Empty, context);
			BuildFilterDefinitions(documentMapping);

			return documentMapping;
		}
        public DirectoryProviders CreateDirectoryProviders(DocumentMapping classMapping, Configuration cfg,
                                                          ISearchFactoryImplementor searchFactoryImplementor)
        {
            // Get properties
            string directoryProviderName = GetDirectoryProviderName(classMapping, cfg);
            IDictionary<string, string>[] indexProps = GetDirectoryProperties(cfg, directoryProviderName);

            // Set up the directories
            int nbrOfProviders = indexProps.Length;
            IDirectoryProvider[] providers = new IDirectoryProvider[nbrOfProviders];
            for (int index = 0; index < nbrOfProviders; index++)
            {
                string providerName = nbrOfProviders > 1
                                          ? directoryProviderName + "." + index
                                          : directoryProviderName;

                // NB Are the properties nested??
                providers[index] = CreateDirectoryProvider(providerName, indexProps[index], searchFactoryImplementor);
            }

            // Define sharding strategy
            IIndexShardingStrategy shardingStrategy;
            IDictionary<string, string> shardingProperties = new Dictionary<string, string>();

            // Any indexProperty will do, the indexProps[0] surely exists.
            foreach (KeyValuePair<string, string> entry in indexProps[0])
            {
                if (entry.Key.StartsWith(SHARDING_STRATEGY))
                {
                    shardingProperties.Add(entry);
                }
            }

            string shardingStrategyName;
            shardingProperties.TryGetValue(SHARDING_STRATEGY, out shardingStrategyName);
            if (string.IsNullOrEmpty(shardingStrategyName))
            {
                if (indexProps.Length == 1)
                {
                    shardingStrategy = new NotShardedStrategy();
                }
                else
                {
                    shardingStrategy = new IdHashShardingStrategy();
                }
            }
            else
            {
                try
                {
                    System.Type shardingStrategyClass = ReflectHelper.ClassForName(shardingStrategyName);
                    shardingStrategy = (IIndexShardingStrategy) Activator.CreateInstance(shardingStrategyClass);
                }
                catch
                {
                    // TODO: See if we can get a tigher exception trap here
                    throw new SearchException("Failed to instantiate lucene analyzer with type  " + shardingStrategyName);
                }
            }

            shardingStrategy.Initialize(shardingProperties, providers);

            return new DirectoryProviders(shardingStrategy, providers);
        }
 private string GetDirectoryProviderName(DocumentMapping documentMapping, Configuration cfg)
 {
     return string.IsNullOrEmpty(documentMapping.IndexName)
          ? documentMapping.MappedClass.Name
          : documentMapping.IndexName;
 }
        private void BindFilterDefs(DocumentMapping mappedClass)
        {
            // We only need one test here as we just support multiple FullTextFilter attributes rather than a collection
            foreach (var filterDef in mappedClass.FullTextFilterDefinitions)
            {
                if (filterDefinitions.ContainsKey(filterDef.Name))
                    throw new SearchException("Multiple definitions of FullTextFilterDef.Name = " + filterDef.Name + ":" +
                                              mappedClass.MappedClass.FullName);

                filterDefinitions[filterDef.Name] = filterDef;
            }
        }
Пример #9
0
        private void CollectAnalyzers(
            DocumentMapping @class, Analyzer parentAnalyzer, bool isRoot, string prefix, ISet<System.Type> processedClasses
        )
        {
            foreach (var bridge in @class.ClassBridges)
            {
                var bridgeAnalyzer = bridge.Analyzer ?? parentAnalyzer;
                if (bridgeAnalyzer == null)
                {
                    throw new NotSupportedException("Analyzer should not be undefined");
                }

                analyzer.AddScopedAnalyzer(prefix + bridge.Name, bridgeAnalyzer);
            }

            if (isRoot && @class.DocumentId != null)
            {
                idMapping = @class.DocumentId;
            }

            foreach (var field in @class.Fields)
            {
                CollectAnalyzer(field, parentAnalyzer, prefix);
            }

            foreach (var embedded in @class.Embedded)
            {
                CollectAnalyzers(
                    embedded.Class, parentAnalyzer, false, prefix + embedded.Prefix, processedClasses
                );
            }
        }
Пример #10
0
        private void BuildDocumentFields(Object instance, Document doc, DocumentMapping classMapping, string prefix)
        {
            if (instance == null)
            {
                return;
            }

            object unproxiedInstance = Unproxy(instance);
            foreach (var bridge in classMapping.ClassBridges)
            {
                var bridgeName = prefix + bridge.Name;
                try
                {
                    bridge.Bridge.Set(
                        bridgeName,
                        unproxiedInstance,
                        doc,
                        GetStore(bridge.Store),
                        GetIndex(bridge.Index),
                        bridge.Boost
                    );
                }
                catch (Exception e)
                {
                    logger.Error(
                        string.Format(CultureInfo.InvariantCulture, "Error processing class bridge for {0}",
                                      bridgeName), e);
                }
            }

            foreach (var field in classMapping.Fields)
            {
                BuildDocumentField(field, unproxiedInstance, doc, prefix);
            }

            foreach (var embedded in classMapping.Embedded)
            {
                BuildDocumentFieldsForEmbedded(embedded, unproxiedInstance, doc, prefix);
            }
        }
Пример #11
0
        private static void ProcessFieldsForProjection(
            DocumentMapping mapping, String[] fields, Object[] result, Document document
        )
        {
            foreach (var field in mapping.Fields)
            {
                PopulateResult(
                    field,
                    fields,
                    result,
                    document
               );
            }

            foreach (var embedded in mapping.Embedded)
            {
                if (!embedded.IsCollection)
                    ProcessFieldsForProjection(embedded.Class, fields, result, document);
            }
        }
Пример #12
0
        private static void ProcessContainedIn(Object instance, List<LuceneWork> queue, DocumentMapping documentMapping,
                                               ISearchFactoryImplementor searchFactoryImplementor)
        {
            foreach (var containedIn in documentMapping.ContainedIn)
            {
                object value = containedIn.Getter.Get(instance);

                if (value == null) continue;

                Array array = value as Array;
                if (array != null)
                {
                    foreach (object arrayValue in array)
                    {
                        // Highly inneficient but safe wrt the actual targeted class, e.g. polymorphic items in the array
                        System.Type valueType = NHibernateUtil.GetClass(arrayValue);
                        if (valueType == null || !searchFactoryImplementor.DocumentBuilders.ContainsKey(valueType))
                        {
                            continue;
                        }

                        ProcessContainedInValue(arrayValue, queue, valueType, searchFactoryImplementor.DocumentBuilders[valueType],
                                                searchFactoryImplementor);
                    }
                }
                else if (typeof(IEnumerable).IsAssignableFrom(value.GetType()))
                {
                    // NB We only see ISet and IDictionary`2 as IEnumerable
                    IEnumerable collection = value as IEnumerable;
                    if (typeof(IDictionary).IsAssignableFrom(value.GetType()))
                    {
                        collection = ((IDictionary) value).Values;
                    }

                    if (collection == null)
                    {
                        continue;
                    }

                    foreach (object collectionValue in collection)
                    {
                        // Highly inneficient but safe wrt the actual targeted class, e.g. polymorphic items in the array
                        System.Type valueType = NHibernateUtil.GetClass(collectionValue);
                        if (valueType == null || !searchFactoryImplementor.DocumentBuilders.ContainsKey(valueType))
                        {
                            continue;
                        }

                        ProcessContainedInValue(collectionValue, queue, valueType,
                                                searchFactoryImplementor.DocumentBuilders[valueType], searchFactoryImplementor);
                    }
                }
                else
                {
                    System.Type valueType = NHibernateUtil.GetClass(value);
                    if (valueType == null || !searchFactoryImplementor.DocumentBuilders.ContainsKey(valueType))
                    {
                        continue;
                    }

                    ProcessContainedInValue(value, queue, valueType, searchFactoryImplementor.DocumentBuilders[valueType],
                                            searchFactoryImplementor);
                }
            }

            //an embedded cannot have a useful @ContainedIn (no shared reference)
            //do not walk through them
        }
Пример #13
0
        private static void ProcessFieldsForProjection(
            DocumentMapping mapping, String[] fields, Object[] result, Document document, string prefix
        )
        {
            foreach (var field in mapping.Fields)
            {
                PopulateResult(
                    prefix + field.Name,
                    field.Bridge,
                    field.Store,
                    fields,
                    result,
                    document
               );
            }

            foreach (var embedded in mapping.Embedded)
            {
                if (!embedded.IsCollection)
                    ProcessFieldsForProjection(embedded.Class, fields, result, document, prefix + embedded.Prefix);
            }
        }
		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));
			}
		}