1 package org.apache.lucene.search; 2 3 18 19 import java.io.IOException ; 20 21 final class BooleanScorer extends Scorer { 22 private SubScorer scorers = null; 23 private BucketTable bucketTable = new BucketTable(this); 24 25 private int maxCoord = 1; 26 private float[] coordFactors = null; 27 28 private int requiredMask = 0; 29 private int prohibitedMask = 0; 30 private int nextMask = 1; 31 32 BooleanScorer(Similarity similarity) { 33 super(similarity); 34 } 35 36 static final class SubScorer { 37 public Scorer scorer; 38 public boolean done; 39 public boolean required = false; 40 public boolean prohibited = false; 41 public HitCollector collector; 42 public SubScorer next; 43 44 public SubScorer(Scorer scorer, boolean required, boolean prohibited, 45 HitCollector collector, SubScorer next) 46 throws IOException { 47 this.scorer = scorer; 48 this.done = !scorer.next(); 49 this.required = required; 50 this.prohibited = prohibited; 51 this.collector = collector; 52 this.next = next; 53 } 54 } 55 56 final void add(Scorer scorer, boolean required, boolean prohibited) 57 throws IOException { 58 int mask = 0; 59 if (required || prohibited) { 60 if (nextMask == 0) 61 throw new IndexOutOfBoundsException 62 ("More than 32 required/prohibited clauses in query."); 63 mask = nextMask; 64 nextMask = nextMask << 1; 65 } else 66 mask = 0; 67 68 if (!prohibited) 69 maxCoord++; 70 71 if (prohibited) 72 prohibitedMask |= mask; else if (required) 74 requiredMask |= mask; 76 scorers = new SubScorer(scorer, required, prohibited, 77 bucketTable.newCollector(mask), scorers); 78 } 79 80 private final void computeCoordFactors() { 81 coordFactors = new float[maxCoord]; 82 for (int i = 0; i < maxCoord; i++) 83 coordFactors[i] = getSimilarity().coord(i, maxCoord-1); 84 } 85 86 private int end; 87 private Bucket current; 88 89 public void score(HitCollector hc) throws IOException { 90 next(); 91 score(hc, Integer.MAX_VALUE); 92 } 93 94 protected boolean score(HitCollector hc, int max) throws IOException { 95 if (coordFactors == null) 96 computeCoordFactors(); 97 98 boolean more; 99 Bucket tmp; 100 101 do { 102 bucketTable.first = null; 103 104 while (current != null) { 106 if ((current.bits & prohibitedMask) == 0 && 108 (current.bits & requiredMask) == requiredMask) { 109 110 if (current.doc >= max){ 111 tmp = current; 112 current = current.next; 113 tmp.next = bucketTable.first; 114 bucketTable.first = tmp; 115 continue; 116 } 117 118 hc.collect(current.doc, current.score * coordFactors[current.coord]); 119 } 120 121 current = current.next; } 123 124 if( bucketTable.first != null){ 125 current = bucketTable.first; 126 bucketTable.first = current.next; 127 return true; 128 } 129 130 more = false; 132 end += BucketTable.SIZE; 133 for (SubScorer sub = scorers; sub != null; sub = sub.next) { 134 if (!sub.done) { 135 sub.done = !sub.scorer.score(sub.collector, end); 136 if (!sub.done) 137 more = true; 138 } 139 } 140 current = bucketTable.first; 141 142 } while (current != null || more); 143 144 return false; 145 } 146 147 public int doc() { return current.doc; } 148 149 public boolean next() throws IOException { 150 boolean more; 151 do { 152 while (bucketTable.first != null) { current = bucketTable.first; 154 bucketTable.first = current.next; 156 if ((current.bits & prohibitedMask) == 0 && 158 (current.bits & requiredMask) == requiredMask) { 159 return true; 160 } 161 } 162 163 more = false; 165 end += BucketTable.SIZE; 166 for (SubScorer sub = scorers; sub != null; sub = sub.next) { 167 Scorer scorer = sub.scorer; 168 while (!sub.done && scorer.doc() < end) { 169 sub.collector.collect(scorer.doc(), scorer.score()); 170 sub.done = !scorer.next(); 171 } 172 if (!sub.done) { 173 more = true; 174 } 175 } 176 } while (bucketTable.first != null || more); 177 178 return false; 179 } 180 181 public float score() { 182 if (coordFactors == null) 183 computeCoordFactors(); 184 return current.score * coordFactors[current.coord]; 185 } 186 187 static final class Bucket { 188 int doc = -1; float score; int bits; int coord; Bucket next; } 194 195 196 static final class BucketTable { 197 public static final int SIZE = 1 << 11; 198 public static final int MASK = SIZE - 1; 199 200 final Bucket[] buckets = new Bucket[SIZE]; 201 Bucket first = null; 203 private BooleanScorer scorer; 204 205 public BucketTable(BooleanScorer scorer) { 206 this.scorer = scorer; 207 } 208 209 public final int size() { return SIZE; } 210 211 public HitCollector newCollector(int mask) { 212 return new Collector(mask, this); 213 } 214 } 215 216 static final class Collector extends HitCollector { 217 private BucketTable bucketTable; 218 private int mask; 219 public Collector(int mask, BucketTable bucketTable) { 220 this.mask = mask; 221 this.bucketTable = bucketTable; 222 } 223 public final void collect(final int doc, final float score) { 224 final BucketTable table = bucketTable; 225 final int i = doc & BucketTable.MASK; 226 Bucket bucket = table.buckets[i]; 227 if (bucket == null) 228 table.buckets[i] = bucket = new Bucket(); 229 230 if (bucket.doc != doc) { bucket.doc = doc; bucket.score = score; bucket.bits = mask; bucket.coord = 1; 236 bucket.next = table.first; table.first = bucket; 238 } else { bucket.score += score; bucket.bits |= mask; bucket.coord++; } 243 } 244 } 245 246 public boolean skipTo(int target) { 247 throw new UnsupportedOperationException (); 248 } 249 250 public Explanation explain(int doc) { 251 throw new UnsupportedOperationException (); 252 } 253 254 public String toString() { 255 StringBuffer buffer = new StringBuffer (); 256 buffer.append("boolean("); 257 for (SubScorer sub = scorers; sub != null; sub = sub.next) { 258 buffer.append(sub.scorer.toString()); 259 buffer.append(" "); 260 } 261 buffer.append(")"); 262 return buffer.toString(); 263 } 264 265 266 } 267 | Popular Tags |