@@ -9,157 +9,144 @@ namespace NHibernate.Search.Filter
9
9
using Lucene . Net . Index ;
10
10
using Lucene . Net . Search ;
11
11
12
+ /// <summary>
13
+ /// A filter that performs a Boolean AND on multiple filters.
14
+ /// </summary>
12
15
public class ChainedFilter : Filter
13
16
{
14
- private readonly List < Filter > chainedFilters = new List < Filter > ( ) ;
15
-
16
- public void AddFilter ( Filter filter )
17
- {
18
- chainedFilters . Add ( filter ) ;
19
- }
20
-
21
- public override DocIdSet GetDocIdSet ( IndexReader reader )
22
- {
23
- if ( chainedFilters . Count == 0 )
24
- {
25
- throw new AssertionFailure ( "ChainedFilter has no filters to chain for" ) ;
26
- }
27
-
28
- // We need to copy the first BitArray because BitArray is assigned to by And
29
- HashSet < int > result = null ;
30
-
31
- foreach ( var filter in chainedFilters )
32
- {
33
- DocIdSet b2 = filter . GetDocIdSet ( reader ) ;
34
- int docId ;
35
- DocIdSetIterator iterator = b2 . Iterator ( ) ;
36
-
37
- if ( result == null )
38
- {
39
- result = new HashSet < int > ( ) ;
40
-
41
- while ( ( docId = iterator . NextDoc ( ) ) != DocIdSetIterator . NO_MORE_DOCS )
42
- {
43
- result . Add ( docId ) ;
44
- }
45
- }
46
- else
47
- {
48
- while ( ( docId = iterator . NextDoc ( ) ) != DocIdSetIterator . NO_MORE_DOCS )
49
- {
50
- if ( ! result . Contains ( docId ) )
51
- {
52
- result . Remove ( docId ) ;
53
- }
54
- }
55
- }
56
- }
57
-
58
- DocIdSet filteredCombinedDocIdSet = new EnumerableBasedDocIdSet ( result ) ;
59
- return filteredCombinedDocIdSet ;
60
- }
61
-
62
- public override string ToString ( )
63
- {
64
- StringBuilder sb = new StringBuilder ( "ChainedFilter [" ) ;
65
- foreach ( Filter filter in chainedFilters )
66
- {
67
- sb . AppendLine ( ) . Append ( filter . ToString ( ) ) ;
68
- }
69
-
70
- return sb . Append ( "\r \n ]" ) . ToString ( ) ;
71
- }
72
- }
73
-
74
- public class EnumerableBasedDocIdSet : DocIdSet
75
- {
76
- private readonly IEnumerable < int > _items ;
77
-
78
- public EnumerableBasedDocIdSet ( IEnumerable < int > items )
79
- {
80
- if ( items == null )
81
- {
82
- throw new ArgumentNullException ( "items" ) ;
83
- }
84
-
85
- _items = items ;
86
- }
87
-
88
- /// <summary>
89
- /// Provides a <see cref="T:Lucene.Net.Search.DocIdSetIterator"/> to access the set.
90
- /// This implementation can return <c>null</c> or
91
- /// <c>EMPTY_DOCIDSET.Iterator()</c> if there
92
- /// are no docs that match.
93
- /// </summary>
94
- public override DocIdSetIterator Iterator ( )
95
- {
96
- return new EnumerableBasedDocIdSetIterator ( _items ) ;
97
- }
98
- }
99
-
100
- public class EnumerableBasedDocIdSetIterator : DocIdSetIterator
101
- {
102
- private readonly IEnumerable < int > items ;
103
- private IEnumerator < int > iterator ;
104
- private int ? currentIndex ;
105
-
106
- public EnumerableBasedDocIdSetIterator ( IEnumerable < int > items )
107
- {
108
- if ( items == null )
109
- {
110
- throw new ArgumentNullException ( "items" ) ;
111
- }
112
-
113
- this . items = items ;
114
- iterator = items . GetEnumerator ( ) ;
115
- }
116
-
117
- public override int Advance ( int target )
118
- {
119
- if ( currentIndex == null )
120
- {
121
- currentIndex = 0 ;
122
- }
123
-
124
- if ( target < currentIndex )
125
- {
126
- throw new ArgumentOutOfRangeException ( "target" , target , "Iterator state past target: " + currentIndex ) ;
127
- }
128
-
129
- int remaining = target - currentIndex . Value ;
130
- bool hasMore ;
131
-
132
- while ( ( hasMore = iterator . MoveNext ( ) ) && remaining > 0 )
133
- {
134
- currentIndex ++ ;
135
- }
136
-
137
- if ( ! hasMore )
138
- {
139
- currentIndex = NO_MORE_DOCS ;
140
- }
141
-
142
- return currentIndex == NO_MORE_DOCS ? NO_MORE_DOCS : iterator . Current ;
143
- }
144
-
145
- public override int DocID ( )
146
- {
147
- if ( currentIndex == NO_MORE_DOCS || currentIndex == null )
148
- {
149
- return NO_MORE_DOCS ;
150
- }
151
-
152
- return iterator . Current ;
153
- }
154
-
155
- public override int NextDoc ( )
156
- {
157
- if ( currentIndex == NO_MORE_DOCS )
158
- {
159
- return NO_MORE_DOCS ;
160
- }
161
-
162
- return Advance ( currentIndex . Value + 1 ) ;
163
- }
164
- }
17
+ private readonly List < Filter > chainedFilters = new List < Filter > ( ) ;
18
+
19
+ public void AddFilter ( Filter filter )
20
+ {
21
+ chainedFilters . Add ( filter ) ;
22
+ }
23
+
24
+ private HashSet < int > DocIdSetToHashSet ( DocIdSet docs )
25
+ {
26
+ var result = new HashSet < int > ( ) ;
27
+ var iterator = docs . Iterator ( ) ;
28
+
29
+ int docId ;
30
+ while ( ( docId = iterator . NextDoc ( ) ) != DocIdSetIterator . NO_MORE_DOCS )
31
+ result . Add ( docId ) ;
32
+
33
+ return result ;
34
+ }
35
+
36
+ public override DocIdSet GetDocIdSet ( IndexReader reader )
37
+ {
38
+ if ( chainedFilters . Count == 0 )
39
+ {
40
+ throw new AssertionFailure ( "ChainedFilter has no filters to chain for" ) ;
41
+ }
42
+
43
+ // Create HashSet of first filter's contents
44
+ HashSet < int > result = DocIdSetToHashSet ( chainedFilters [ 0 ] . GetDocIdSet ( reader ) ) ;
45
+
46
+ // For each remaining filter, fill another HashSet and intersect it with the first.
47
+ for ( int i = 1 ; i < chainedFilters . Count ; i ++ )
48
+ {
49
+ var nextSet = DocIdSetToHashSet ( chainedFilters [ i ] . GetDocIdSet ( reader ) ) ;
50
+ result . IntersectWith ( nextSet ) ;
51
+ }
52
+
53
+ DocIdSet resultDocIds = new EnumerableBasedDocIdSet ( result ) ;
54
+ return resultDocIds ;
55
+ }
56
+
57
+
58
+ public override string ToString ( )
59
+ {
60
+ StringBuilder sb = new StringBuilder ( "ChainedFilter [" ) ;
61
+ foreach ( Filter filter in chainedFilters )
62
+ {
63
+ sb . AppendLine ( ) . Append ( filter . ToString ( ) ) ;
64
+ }
65
+
66
+ return sb . Append ( "\r \n ]" ) . ToString ( ) ;
67
+ }
68
+ }
69
+
70
+ public class EnumerableBasedDocIdSet : DocIdSet
71
+ {
72
+ private readonly IEnumerable < int > _items ;
73
+
74
+ public EnumerableBasedDocIdSet ( IEnumerable < int > items )
75
+ {
76
+ if ( items == null )
77
+ {
78
+ throw new ArgumentNullException ( "items" ) ;
79
+ }
80
+
81
+ _items = items ;
82
+ }
83
+
84
+ /// <summary>
85
+ /// Provides a <see cref="T:Lucene.Net.Search.DocIdSetIterator"/> to access the set.
86
+ /// This implementation can return <c>null</c> or
87
+ /// <c>EMPTY_DOCIDSET.Iterator()</c> if there
88
+ /// are no docs that match.
89
+ /// </summary>
90
+ public override DocIdSetIterator Iterator ( )
91
+ {
92
+ return new EnumerableBasedDocIdSetIterator ( _items ) ;
93
+ }
94
+ }
95
+
96
+ public class EnumerableBasedDocIdSetIterator : DocIdSetIterator
97
+ {
98
+ private readonly IEnumerable < int > items ;
99
+ private IEnumerator < int > iterator ;
100
+ private int currentIndex = - 1 ;
101
+
102
+ public EnumerableBasedDocIdSetIterator ( IEnumerable < int > items )
103
+ {
104
+ if ( items == null )
105
+ {
106
+ throw new ArgumentNullException ( "items" ) ;
107
+ }
108
+
109
+ this . items = items ;
110
+ iterator = items . GetEnumerator ( ) ;
111
+ }
112
+
113
+ public override int Advance ( int target )
114
+ {
115
+ if ( target < currentIndex )
116
+ {
117
+ throw new ArgumentOutOfRangeException ( "target" , target , "Iterator state past target: " + currentIndex ) ;
118
+ }
119
+
120
+ // Relies on NO_MORE_DOCS being a big number
121
+ while ( target > currentIndex )
122
+ {
123
+ if ( iterator . MoveNext ( ) )
124
+ currentIndex ++ ;
125
+ else
126
+ currentIndex = NO_MORE_DOCS ;
127
+ }
128
+
129
+ return currentIndex == NO_MORE_DOCS ? NO_MORE_DOCS : iterator . Current ;
130
+ }
131
+
132
+ public override int DocID ( )
133
+ {
134
+ if ( currentIndex == NO_MORE_DOCS || currentIndex == - 1 )
135
+ {
136
+ return NO_MORE_DOCS ;
137
+ }
138
+
139
+ return iterator . Current ;
140
+ }
141
+
142
+ public override int NextDoc ( )
143
+ {
144
+ if ( currentIndex == NO_MORE_DOCS )
145
+ {
146
+ return NO_MORE_DOCS ;
147
+ }
148
+
149
+ return Advance ( currentIndex + 1 ) ;
150
+ }
151
+ }
165
152
}
0 commit comments