1 package org.apache.lucene.search; 2 3 18 19 import java.io.IOException ; 20 import java.util.ArrayList ; 21 import java.util.List ; 22 import java.util.Iterator ; 23 24 28 class BooleanScorer2 extends Scorer { 29 private ArrayList requiredScorers = new ArrayList (); 30 private ArrayList optionalScorers = new ArrayList (); 31 private ArrayList prohibitedScorers = new ArrayList (); 32 33 34 private class Coordinator { 35 int maxCoord = 0; 37 private float[] coordFactors = null; 38 39 void init() { coordFactors = new float[maxCoord + 1]; 41 Similarity sim = getSimilarity(); 42 for (int i = 0; i <= maxCoord; i++) { 43 coordFactors[i] = sim.coord(i, maxCoord); 44 } 45 } 46 47 int nrMatchers; 49 void initDoc() { 50 nrMatchers = 0; 51 } 52 53 float coordFactor() { 54 return coordFactors[nrMatchers]; 55 } 56 } 57 58 private final Coordinator coordinator; 59 60 63 private Scorer countingSumScorer = null; 64 65 66 private final int minNrShouldMatch; 67 68 76 public BooleanScorer2(Similarity similarity, int minNrShouldMatch) { 77 super(similarity); 78 if (minNrShouldMatch < 0) { 79 throw new IllegalArgumentException ("Minimum number of optional scorers should not be negative"); 80 } 81 coordinator = new Coordinator(); 82 this.minNrShouldMatch = minNrShouldMatch; 83 } 84 85 90 public BooleanScorer2(Similarity similarity) { 91 this(similarity, 0); 92 } 93 94 public void add(final Scorer scorer, boolean required, boolean prohibited) { 95 if (!prohibited) { 96 coordinator.maxCoord++; 97 } 98 99 if (required) { 100 if (prohibited) { 101 throw new IllegalArgumentException ("scorer cannot be required and prohibited"); 102 } 103 requiredScorers.add(scorer); 104 } else if (prohibited) { 105 prohibitedScorers.add(scorer); 106 } else { 107 optionalScorers.add(scorer); 108 } 109 } 110 111 118 private void initCountingSumScorer() { 119 coordinator.init(); 120 countingSumScorer = makeCountingSumScorer(); 121 } 122 123 124 private class SingleMatchScorer extends Scorer { 125 private Scorer scorer; 126 private int lastScoredDoc = -1; 127 128 SingleMatchScorer(Scorer scorer) { 129 super(scorer.getSimilarity()); 130 this.scorer = scorer; 131 } 132 public float score() throws IOException { 133 if (doc() > lastScoredDoc) { 134 lastScoredDoc = doc(); 135 coordinator.nrMatchers++; 136 } 137 return scorer.score(); 138 } 139 public int doc() { 140 return scorer.doc(); 141 } 142 public boolean next() throws IOException { 143 return scorer.next(); 144 } 145 public boolean skipTo(int docNr) throws IOException { 146 return scorer.skipTo(docNr); 147 } 148 public Explanation explain(int docNr) throws IOException { 149 return scorer.explain(docNr); 150 } 151 } 152 153 private Scorer countingDisjunctionSumScorer(List scorers, 154 int minMrShouldMatch) 155 { 157 return new DisjunctionSumScorer(scorers, minMrShouldMatch) { 158 private int lastScoredDoc = -1; 159 public float score() throws IOException { 160 if (doc() > lastScoredDoc) { 161 lastScoredDoc = doc(); 162 coordinator.nrMatchers += super.nrMatchers; 163 } 164 return super.score(); 165 } 166 }; 167 } 168 169 private static Similarity defaultSimilarity = new DefaultSimilarity(); 170 171 private Scorer countingConjunctionSumScorer(List requiredScorers) { 172 final int requiredNrMatchers = requiredScorers.size(); 174 ConjunctionScorer cs = new ConjunctionScorer(defaultSimilarity) { 175 private int lastScoredDoc = -1; 176 177 public float score() throws IOException { 178 if (doc() > lastScoredDoc) { 179 lastScoredDoc = doc(); 180 coordinator.nrMatchers += requiredNrMatchers; 181 } 182 return super.score(); 187 } 188 }; 189 Iterator rsi = requiredScorers.iterator(); 190 while (rsi.hasNext()) { 191 cs.add((Scorer) rsi.next()); 192 } 193 return cs; 194 } 195 196 private Scorer dualConjunctionSumScorer(Scorer req1, Scorer req2) { final int requiredNrMatchers = requiredScorers.size(); 198 ConjunctionScorer cs = new ConjunctionScorer(defaultSimilarity); 199 cs.add(req1); 204 cs.add(req2); 205 return cs; 206 } 207 208 211 private Scorer makeCountingSumScorer() { return (requiredScorers.size() == 0) 213 ? makeCountingSumScorerNoReq() 214 : makeCountingSumScorerSomeReq(); 215 } 216 217 private Scorer makeCountingSumScorerNoReq() { if (optionalScorers.size() == 0) { 219 return new NonMatchingScorer(); } else { int nrOptRequired = (minNrShouldMatch < 1) ? 1 : minNrShouldMatch; 223 if (optionalScorers.size() < nrOptRequired) { 224 return new NonMatchingScorer(); } else { Scorer requiredCountingSumScorer = 227 (optionalScorers.size() > nrOptRequired) 228 ? countingDisjunctionSumScorer(optionalScorers, nrOptRequired) 229 : (optionalScorers.size() == 1) 231 ? new SingleMatchScorer((Scorer) optionalScorers.get(0)) 232 : countingConjunctionSumScorer(optionalScorers); 233 return addProhibitedScorers( requiredCountingSumScorer); 234 } 235 } 236 } 237 238 private Scorer makeCountingSumScorerSomeReq() { if (optionalScorers.size() < minNrShouldMatch) { 240 return new NonMatchingScorer(); } else if (optionalScorers.size() == minNrShouldMatch) { ArrayList allReq = new ArrayList (requiredScorers); 243 allReq.addAll(optionalScorers); 244 return addProhibitedScorers( countingConjunctionSumScorer(allReq)); 245 } else { Scorer requiredCountingSumScorer = 247 (requiredScorers.size() == 1) 248 ? new SingleMatchScorer((Scorer) requiredScorers.get(0)) 249 : countingConjunctionSumScorer(requiredScorers); 250 if (minNrShouldMatch > 0) { return addProhibitedScorers( 252 dualConjunctionSumScorer( requiredCountingSumScorer, 254 countingDisjunctionSumScorer( 255 optionalScorers, 256 minNrShouldMatch))); 257 } else { return new ReqOptSumScorer( 259 addProhibitedScorers(requiredCountingSumScorer), 260 ((optionalScorers.size() == 1) 261 ? new SingleMatchScorer((Scorer) optionalScorers.get(0)) 262 : countingDisjunctionSumScorer(optionalScorers, 1))); } 264 } 265 } 266 267 271 private Scorer addProhibitedScorers(Scorer requiredCountingSumScorer) 272 { 273 return (prohibitedScorers.size() == 0) 274 ? requiredCountingSumScorer : new ReqExclScorer(requiredCountingSumScorer, 276 ((prohibitedScorers.size() == 1) 277 ? (Scorer) prohibitedScorers.get(0) 278 : new DisjunctionSumScorer(prohibitedScorers))); 279 } 280 281 286 public void score(HitCollector hc) throws IOException { 287 if (countingSumScorer == null) { 288 initCountingSumScorer(); 289 } 290 while (countingSumScorer.next()) { 291 hc.collect(countingSumScorer.doc(), score()); 292 } 293 } 294 295 303 protected boolean score(HitCollector hc, int max) throws IOException { 304 int docNr = countingSumScorer.doc(); 306 while (docNr < max) { 307 hc.collect(docNr, score()); 308 if (! countingSumScorer.next()) { 309 return false; 310 } 311 docNr = countingSumScorer.doc(); 312 } 313 return true; 314 } 315 316 public int doc() { return countingSumScorer.doc(); } 317 318 public boolean next() throws IOException { 319 if (countingSumScorer == null) { 320 initCountingSumScorer(); 321 } 322 return countingSumScorer.next(); 323 } 324 325 public float score() throws IOException { 326 coordinator.initDoc(); 327 float sum = countingSumScorer.score(); 328 return sum * coordinator.coordFactor(); 329 } 330 331 339 public boolean skipTo(int target) throws IOException { 340 if (countingSumScorer == null) { 341 initCountingSumScorer(); 342 } 343 return countingSumScorer.skipTo(target); 344 } 345 346 351 public Explanation explain(int doc) { 352 throw new UnsupportedOperationException (); 353 357 } 358 } 359 360 | Popular Tags |