@@ -117,7 +117,7 @@ public static DocBlockGroupingSearch<TGroupValue> ByDocBlock<TGroupValue>(Filter
117117 /// The group field can only have one token per document. This means that the field must not be analysed.
118118 /// </summary>
119119 /// <seealso cref="GroupingSearch.ByField(string)"/>
120- public class FieldGroupingSearch : AbstractFieldOrFunctionGroupingSearch < BytesRef >
120+ public class FieldGroupingSearch : AbstractFieldOrFunctionGroupingSearch < BytesRef , FieldGroupingSearch >
121121 {
122122 private readonly string groupField ;
123123 private int initialSize = 128 ;
@@ -131,7 +131,7 @@ public FieldGroupingSearch(string groupField)
131131 this . groupField = groupField ;
132132 }
133133
134- /// <inheritdoc cref="AbstractGroupingSearch{T}.Search(IndexSearcher,Filter,Query,int,int)"/>
134+ /// <inheritdoc cref="AbstractGroupingSearch{T, TSelf }.Search(IndexSearcher,Filter,Query,int,int)"/>
135135 public override TopGroups < BytesRef > Search ( IndexSearcher searcher , Filter filter , Query query , int groupOffset , int groupLimit )
136136 {
137137 int topN = groupOffset + groupLimit ;
@@ -255,8 +255,8 @@ public override TopGroups<BytesRef> Search(IndexSearcher searcher, Filter filter
255255 /// This prevents growing data structures many times. This can improve the performance of the grouping at the cost of
256256 /// more initial RAM.
257257 /// <para>
258- /// The <see cref="AbstractFieldOrFunctionGroupingSearch{T}.SetAllGroups(bool)"/> and
259- /// <see cref="AbstractFieldOrFunctionGroupingSearch{T}.SetAllGroupHeads(bool)"/> features use this option.
258+ /// The <see cref="AbstractFieldOrFunctionGroupingSearch{T, TSelf }.SetAllGroups(bool)"/> and
259+ /// <see cref="AbstractFieldOrFunctionGroupingSearch{T, TSelf }.SetAllGroupHeads(bool)"/> features use this option.
260260 /// Defaults to 128.
261261 /// </para>
262262 /// </summary>
@@ -274,7 +274,7 @@ public virtual FieldGroupingSearch SetInitialSize(int initialSize)
274274 /// </summary>
275275 /// <typeparam name="T">The type of the mutable value</typeparam>
276276 /// <seealso cref="GroupingSearch.ByFunction{TMutableValue}(ValueSource, IDictionary)"/>
277- public class FunctionGroupingSearch < T > : AbstractFieldOrFunctionGroupingSearch < T >
277+ public class FunctionGroupingSearch < T > : AbstractFieldOrFunctionGroupingSearch < T , FunctionGroupingSearch < T > >
278278 where T : MutableValue
279279 {
280280 private readonly ValueSource groupFunction ;
@@ -291,7 +291,7 @@ public FunctionGroupingSearch(ValueSource groupFunction, IDictionary /* Map<?, ?
291291 this . valueSourceContext = valueSourceContext ;
292292 }
293293
294- /// <inheritdoc cref="AbstractGroupingSearch{T}.Search(IndexSearcher,Filter,Query,int,int)"/>
294+ /// <inheritdoc cref="AbstractGroupingSearch{T, TSelf }.Search(IndexSearcher,Filter,Query,int,int)"/>
295295 public override TopGroups < T > Search ( IndexSearcher searcher , Filter filter , Query query , int groupOffset , int groupLimit )
296296 {
297297 int topN = groupOffset + groupLimit ;
@@ -418,7 +418,7 @@ public override TopGroups<T> Search(IndexSearcher searcher, Filter filter, Query
418418 /// This class can only be used when documents belonging in a group are indexed in one block.
419419 /// </summary>
420420 /// <typeparam name="T">The type of the group value</typeparam>
421- public class DocBlockGroupingSearch < T > : AbstractGroupingSearch < T >
421+ public class DocBlockGroupingSearch < T > : AbstractGroupingSearch < T , DocBlockGroupingSearch < T > >
422422 {
423423 private readonly Filter groupEndDocs ;
424424
@@ -432,7 +432,7 @@ public DocBlockGroupingSearch(Filter groupEndDocs)
432432 this . groupEndDocs = groupEndDocs ;
433433 }
434434
435- /// <inheritdoc cref="AbstractGroupingSearch{T}.Search(IndexSearcher,Filter,Query,int,int)"/>
435+ /// <inheritdoc cref="AbstractGroupingSearch{T, TSelf }.Search(IndexSearcher,Filter,Query,int,int)"/>
436436 public override TopGroups < T > Search ( IndexSearcher searcher , Filter filter , Query query , int groupOffset , int groupLimit )
437437 {
438438 int topN = groupOffset + groupLimit ;
@@ -447,11 +447,13 @@ public override TopGroups<T> Search(IndexSearcher searcher, Filter filter, Query
447447 /// Abstract base class for grouping search implementations that groups documents by index terms or function.
448448 /// </summary>
449449 /// <typeparam name="T">The type of the group value</typeparam>
450+ /// <typeparam name="TSelf">The type of the concrete grouping search implementation, used for fluent method chaining</typeparam>
450451 /// <remarks>
451452 /// LUCENENET specific
452453 /// </remarks>
453454 /// <seealso cref="GroupingSearch"/>
454- public abstract class AbstractFieldOrFunctionGroupingSearch < T > : AbstractGroupingSearch < T >
455+ public abstract class AbstractFieldOrFunctionGroupingSearch < T , TSelf > : AbstractGroupingSearch < T , TSelf >
456+ where TSelf : AbstractFieldOrFunctionGroupingSearch < T , TSelf >
455457 {
456458 // LUCENENET: Converted to protected properties
457459 protected bool IncludeMaxScore { get ; private set ; } = true ;
@@ -473,12 +475,12 @@ public abstract class AbstractFieldOrFunctionGroupingSearch<T> : AbstractGroupin
473475 /// <param name="maxCacheRAMMB">The maximum amount in MB the cache is allowed to hold</param>
474476 /// <param name="cacheScores">Whether to cache the scores</param>
475477 /// <returns><c>this</c></returns>
476- public virtual AbstractGroupingSearch < T > SetCachingInMB ( double maxCacheRAMMB , bool cacheScores )
478+ public virtual TSelf SetCachingInMB ( double maxCacheRAMMB , bool cacheScores )
477479 {
478480 this . MaxCacheRAMMB = maxCacheRAMMB ;
479481 this . MaxDocsToCache = null ;
480482 this . CacheScores = cacheScores ;
481- return this ;
483+ return ( TSelf ) this ;
482484 }
483485
484486 /// <summary>
@@ -489,34 +491,34 @@ public virtual AbstractGroupingSearch<T> SetCachingInMB(double maxCacheRAMMB, bo
489491 /// <param name="maxDocsToCache">The maximum number of documents the cache is allowed to hold</param>
490492 /// <param name="cacheScores">Whether to cache the scores</param>
491493 /// <returns><c>this</c></returns>
492- public virtual AbstractGroupingSearch < T > SetCaching ( int maxDocsToCache , bool cacheScores )
494+ public virtual TSelf SetCaching ( int maxDocsToCache , bool cacheScores )
493495 {
494496 this . MaxDocsToCache = maxDocsToCache ;
495497 this . MaxCacheRAMMB = null ;
496498 this . CacheScores = cacheScores ;
497- return this ;
499+ return ( TSelf ) this ;
498500 }
499501
500502 /// <summary>
501503 /// Disables any enabled cache.
502504 /// </summary>
503505 /// <returns><c>this</c></returns>
504- public virtual AbstractGroupingSearch < T > DisableCaching ( )
506+ public virtual TSelf DisableCaching ( )
505507 {
506508 this . MaxCacheRAMMB = null ;
507509 this . MaxDocsToCache = null ;
508- return this ;
510+ return ( TSelf ) this ;
509511 }
510512
511513 /// <summary>
512514 /// Whether to include the score of the most relevant document per group.
513515 /// </summary>
514516 /// <param name="includeMaxScore">Whether to include the score of the most relevant document per group</param>
515517 /// <returns><c>this</c></returns>
516- public virtual AbstractGroupingSearch < T > SetIncludeMaxScore ( bool includeMaxScore )
518+ public virtual TSelf SetIncludeMaxScore ( bool includeMaxScore )
517519 {
518520 this . IncludeMaxScore = includeMaxScore ;
519- return this ;
521+ return ( TSelf ) this ;
520522 }
521523
522524 /// <summary>
@@ -529,10 +531,10 @@ public virtual AbstractGroupingSearch<T> SetIncludeMaxScore(bool includeMaxScore
529531 /// </summary>
530532 /// <param name="allGroups">to also compute all groups matching the query</param>
531533 /// <returns><c>this</c></returns>
532- public virtual AbstractGroupingSearch < T > SetAllGroups ( bool allGroups )
534+ public virtual TSelf SetAllGroups ( bool allGroups )
533535 {
534536 this . AllGroups = allGroups ;
535- return this ;
537+ return ( TSelf ) this ;
536538 }
537539
538540 /// <summary>
@@ -553,10 +555,10 @@ public virtual ICollection<T> GetAllMatchingGroups()
553555 /// </summary>
554556 /// <param name="allGroupHeads">Whether to compute all group heads (most relevant document per group) matching the query</param>
555557 /// <returns><c>this</c></returns>
556- public virtual AbstractGroupingSearch < T > SetAllGroupHeads ( bool allGroupHeads )
558+ public virtual TSelf SetAllGroupHeads ( bool allGroupHeads )
557559 {
558560 this . AllGroupHeads = allGroupHeads ;
559- return this ;
561+ return ( TSelf ) this ;
560562 }
561563
562564 /// <summary>
@@ -573,11 +575,13 @@ public virtual IBits GetAllGroupHeads()
573575 /// Abstract base class for grouping search implementations.
574576 /// </summary>
575577 /// <typeparam name="T">The type of the group value</typeparam>
578+ /// <typeparam name="TSelf">The type of the concrete grouping search implementation, used for fluent method chaining</typeparam>
576579 /// <remarks>
577580 /// LUCENENET specific
578581 /// </remarks>
579582 /// <seealso cref="GroupingSearch"/>
580- public abstract class AbstractGroupingSearch < T > : IAbstractGroupingSearch
583+ public abstract class AbstractGroupingSearch < T , TSelf > : IAbstractGroupingSearch
584+ where TSelf : AbstractGroupingSearch < T , TSelf >
581585 {
582586 // LUCENENET: Converted to protected properties
583587 protected Sort GroupSort { get ; private set ; } = Sort . RELEVANCE ;
@@ -618,10 +622,10 @@ public TopGroups<T> Search(IndexSearcher searcher, Query query, int groupOffset,
618622 /// </summary>
619623 /// <param name="groupSort">The sort for the groups.</param>
620624 /// <returns><c>this</c></returns>
621- public virtual AbstractGroupingSearch < T > SetGroupSort ( Sort groupSort )
625+ public virtual TSelf SetGroupSort ( Sort groupSort )
622626 {
623627 this . GroupSort = groupSort ;
624- return this ;
628+ return ( TSelf ) this ;
625629 }
626630
627631 /// <summary>
@@ -630,54 +634,54 @@ public virtual AbstractGroupingSearch<T> SetGroupSort(Sort groupSort)
630634 /// </summary>
631635 /// <param name="sortWithinGroup">The sort for documents inside a group</param>
632636 /// <returns><c>this</c></returns>
633- public virtual AbstractGroupingSearch < T > SetSortWithinGroup ( Sort sortWithinGroup )
637+ public virtual TSelf SetSortWithinGroup ( Sort sortWithinGroup )
634638 {
635639 this . SortWithinGroup = sortWithinGroup ;
636- return this ;
640+ return ( TSelf ) this ;
637641 }
638642
639643 /// <summary>
640644 /// Specifies the offset for documents inside a group.
641645 /// </summary>
642646 /// <param name="groupDocsOffset">The offset for documents inside a</param>
643647 /// <returns><c>this</c></returns>
644- public virtual AbstractGroupingSearch < T > SetGroupDocsOffset ( int groupDocsOffset )
648+ public virtual TSelf SetGroupDocsOffset ( int groupDocsOffset )
645649 {
646650 this . GroupDocsOffset = groupDocsOffset ;
647- return this ;
651+ return ( TSelf ) this ;
648652 }
649653
650654 /// <summary>
651655 /// Specifies the number of documents to return inside a group from the specified groupDocsOffset.
652656 /// </summary>
653657 /// <param name="groupDocsLimit">The number of documents to return inside a group</param>
654658 /// <returns><c>this</c></returns>
655- public virtual AbstractGroupingSearch < T > SetGroupDocsLimit ( int groupDocsLimit )
659+ public virtual TSelf SetGroupDocsLimit ( int groupDocsLimit )
656660 {
657661 this . GroupDocsLimit = groupDocsLimit ;
658- return this ;
662+ return ( TSelf ) this ;
659663 }
660664
661665 /// <summary>
662666 /// Whether to also fill the sort fields per returned group and groups docs.
663667 /// </summary>
664668 /// <param name="fillSortFields">Whether to also fill the sort fields per returned group and groups docs</param>
665669 /// <returns><c>this</c></returns>
666- public virtual AbstractGroupingSearch < T > SetFillSortFields ( bool fillSortFields )
670+ public virtual TSelf SetFillSortFields ( bool fillSortFields )
667671 {
668672 this . FillSortFields = fillSortFields ;
669- return this ;
673+ return ( TSelf ) this ;
670674 }
671675
672676 /// <summary>
673677 /// Whether to include the scores per doc inside a group.
674678 /// </summary>
675679 /// <param name="includeScores">Whether to include the scores per doc inside a group</param>
676680 /// <returns><c>this</c></returns>
677- public virtual AbstractGroupingSearch < T > SetIncludeScores ( bool includeScores )
681+ public virtual TSelf SetIncludeScores ( bool includeScores )
678682 {
679683 this . IncludeScores = includeScores ;
680- return this ;
684+ return ( TSelf ) this ;
681685 }
682686
683687 #region Explicit interface implementations
@@ -694,7 +698,7 @@ ITopGroups IAbstractGroupingSearch.Search(IndexSearcher searcher, Filter filter,
694698 }
695699
696700 /// <summary>
697- /// LUCENENET specific interface for non-generic access to <see cref="AbstractGroupingSearch{T}"/>.
701+ /// LUCENENET specific interface for non-generic access to <see cref="AbstractGroupingSearch{T, TSelf }"/>.
698702 /// </summary>
699703 public interface IAbstractGroupingSearch
700704 {
0 commit comments