2 * Copyright 2004 The Apache Software Foundation
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 namespace Lucene
.Net
.Search
20 sealed class BooleanScorer
: Scorer
22 private void InitBlock()
24 bucketTable
= new BucketTable(this);
26 private SubScorer scorers
= null;
27 private BucketTable bucketTable
;
29 private int maxCoord
= 1;
30 private float[] coordFactors
= null;
32 private int requiredMask
= 0;
33 private int prohibitedMask
= 0;
34 private int nextMask
= 1;
36 internal BooleanScorer(Similarity similarity
) : base(similarity
)
41 internal sealed class SubScorer
45 public bool required
= false;
46 public bool prohibited
= false;
47 public HitCollector collector
;
48 public SubScorer next
;
50 public SubScorer(Scorer scorer
, bool required
, bool prohibited
, HitCollector collector
, SubScorer next
)
53 this.done
= !scorer
.Next();
54 this.required
= required
;
55 this.prohibited
= prohibited
;
56 this.collector
= collector
;
61 internal void Add(Scorer scorer
, bool required
, bool prohibited
)
64 if (required
|| prohibited
)
67 throw new System
.IndexOutOfRangeException("More than 32 required/prohibited clauses in query.");
69 nextMask
= nextMask
<< 1;
78 prohibitedMask
|= mask
;
79 // update prohibited mask
81 requiredMask
|= mask
; // update required mask
83 scorers
= new SubScorer(scorer
, required
, prohibited
, bucketTable
.NewCollector(mask
), scorers
);
86 private void ComputeCoordFactors()
88 coordFactors
= new float[maxCoord
];
89 for (int i
= 0; i
< maxCoord
; i
++)
90 coordFactors
[i
] = GetSimilarity().Coord(i
, maxCoord
- 1);
94 private Bucket current
;
96 public override int Doc()
101 public override bool Next()
106 while (bucketTable
.first
!= null)
109 current
= bucketTable
.first
;
110 bucketTable
.first
= current
.next
; // pop the queue
112 // check prohibited & required
113 if ((current
.bits
& prohibitedMask
) == 0 && (current
.bits
& requiredMask
) == requiredMask
)
121 end
+= BucketTable
.SIZE
;
122 for (SubScorer sub
= scorers
; sub
!= null; sub
= sub
.next
)
124 Scorer scorer
= sub
.scorer
;
125 while (!sub
.done
&& scorer
.Doc() < end
)
127 sub
.collector
.Collect(scorer
.Doc(), scorer
.Score());
128 sub
.done
= !scorer
.Next();
136 while (bucketTable
.first
!= null | more
);
141 public override float Score()
143 if (coordFactors
== null)
144 ComputeCoordFactors();
145 return current
.score
* coordFactors
[current
.coord
];
148 internal sealed class Bucket
150 internal int doc
= - 1; // tells if bucket is valid
151 internal float score
; // incremental score
152 internal int bits
; // used for bool constraints
153 internal int coord
; // count of terms in score
154 internal Bucket next
; // next valid bucket
157 /// <summary>A simple hash table of document scores within a range. </summary>
158 internal sealed class BucketTable
160 private void InitBlock()
162 buckets
= new Bucket
[SIZE
];
164 public const int SIZE
= 1 << 10;
165 public static readonly int MASK
;
167 internal Bucket
[] buckets
;
168 internal Bucket first
= null; // head of valid list
170 private BooleanScorer scorer
;
172 public BucketTable(BooleanScorer scorer
)
175 this.scorer
= scorer
;
183 public HitCollector
NewCollector(int mask
)
185 return new Collector(mask
, this);
193 internal sealed class Collector
: HitCollector
195 private BucketTable bucketTable
;
197 public Collector(int mask
, BucketTable bucketTable
)
200 this.bucketTable
= bucketTable
;
202 public override void Collect(int doc
, float score
)
204 BucketTable table
= bucketTable
;
205 int i
= doc
& Lucene
.Net
.Search
.BooleanScorer
.BucketTable
.MASK
;
206 Bucket bucket
= table
.buckets
[i
];
208 table
.buckets
[i
] = bucket
= new Bucket();
210 if (bucket
.doc
!= doc
)
213 bucket
.doc
= doc
; // set doc
214 bucket
.score
= score
; // initialize score
215 bucket
.bits
= mask
; // initialize mask
216 bucket
.coord
= 1; // initialize coord
218 bucket
.next
= table
.first
; // push onto valid list
219 table
.first
= bucket
;
224 bucket
.score
+= score
; // increment score
225 bucket
.bits
|= mask
; // add bits in mask
226 bucket
.coord
++; // increment coord
231 public override bool SkipTo(int target
)
233 throw new System
.NotSupportedException();
236 public override Explanation
Explain(int doc
)
238 throw new System
.NotSupportedException();
241 public override System
.String
ToString()
243 System
.Text
.StringBuilder buffer
= new System
.Text
.StringBuilder();
244 buffer
.Append("boolean(");
245 for (SubScorer sub
= scorers
; sub
!= null; sub
= sub
.next
)
247 buffer
.Append(sub
.scorer
.ToString());
251 return buffer
.ToString();