1 package org.apache.lucene.search; 2 3 18 19 import java.util.List ; 20 import java.util.Iterator ; 21 import java.io.IOException ; 22 23 import org.apache.lucene.util.PriorityQueue; 24 25 28 public class DisjunctionSumScorer extends Scorer { 29 30 private final int nrScorers; 31 32 33 protected final List subScorers; 34 35 36 private final int minimumNrMatchers; 37 38 50 private ScorerQueue scorerQueue = null; 51 52 53 private int currentDoc = -1; 54 55 56 protected int nrMatchers = -1; 57 58 private float currentScore = Float.NaN; 59 60 70 public DisjunctionSumScorer( List subScorers, int minimumNrMatchers) { 71 super(null); 72 73 nrScorers = subScorers.size(); 74 75 if (minimumNrMatchers <= 0) { 76 throw new IllegalArgumentException ("Minimum nr of matchers must be positive"); 77 } 78 if (nrScorers <= 1) { 79 throw new IllegalArgumentException ("There must be at least 2 subScorers"); 80 } 81 82 this.minimumNrMatchers = minimumNrMatchers; 83 this.subScorers = subScorers; 84 } 85 86 89 public DisjunctionSumScorer(List subScorers) { 90 this(subScorers, 1); 91 } 92 93 96 private void initScorerQueue() throws IOException { 97 Iterator si = subScorers.iterator(); 98 scorerQueue = new ScorerQueue(nrScorers); 99 while (si.hasNext()) { 100 Scorer se = (Scorer) si.next(); 101 if (se.next()) { scorerQueue.insert(se); 103 } 104 } 105 } 106 107 108 private class ScorerQueue extends PriorityQueue { 109 ScorerQueue(int size) { 110 initialize(size); 111 } 112 113 protected boolean lessThan(Object o1, Object o2) { 114 return ((Scorer)o1).doc() < ((Scorer)o2).doc(); 115 } 116 } 117 118 public boolean next() throws IOException { 119 if (scorerQueue == null) { 120 initScorerQueue(); 121 } 122 if (scorerQueue.size() < minimumNrMatchers) { 123 return false; 124 } else { 125 return advanceAfterCurrent(); 126 } 127 } 128 129 130 144 protected boolean advanceAfterCurrent() throws IOException { 145 do { Scorer top = (Scorer) scorerQueue.top(); 147 currentDoc = top.doc(); 148 currentScore = top.score(); 149 nrMatchers = 1; 150 do { if (top.next()) { 152 scorerQueue.adjustTop(); 153 } else { 154 scorerQueue.pop(); 155 if (scorerQueue.size() < (minimumNrMatchers - nrMatchers)) { 156 return false; 159 } 160 if (scorerQueue.size() == 0) { 161 break; } 163 } 164 top = (Scorer) scorerQueue.top(); 165 if (top.doc() != currentDoc) { 166 break; } else { 168 currentScore += top.score(); 169 nrMatchers++; 170 } 171 } while (true); 172 173 if (nrMatchers >= minimumNrMatchers) { 174 return true; 175 } else if (scorerQueue.size() < minimumNrMatchers) { 176 return false; 177 } 178 } while (true); 179 } 180 181 184 public float score() throws IOException { return currentScore; } 185 186 public int doc() { return currentDoc; } 187 188 191 public int nrMatchers() { 192 return nrMatchers; 193 } 194 195 202 public boolean skipTo(int target) throws IOException { 203 if (scorerQueue == null) { 204 initScorerQueue(); 205 } 206 if (scorerQueue.size() < minimumNrMatchers) { 207 return false; 208 } 209 if (target <= currentDoc) { 210 target = currentDoc + 1; 211 } 212 do { 213 Scorer top = (Scorer) scorerQueue.top(); 214 if (top.doc() >= target) { 215 return advanceAfterCurrent(); 216 } else if (top.skipTo(target)) { 217 scorerQueue.adjustTop(); 218 } else { 219 scorerQueue.pop(); 220 if (scorerQueue.size() < minimumNrMatchers) { 221 return false; 222 } 223 } 224 } while (true); 225 } 226 227 230 public Explanation explain(int doc) throws IOException { 231 Explanation res = new Explanation(); 232 res.setDescription("At least " + minimumNrMatchers + " of"); 233 Iterator ssi = subScorers.iterator(); 234 while (ssi.hasNext()) { 235 res.addDetail( ((Scorer) ssi.next()).explain(doc)); 236 } 237 return res; 238 } 239 } 240 | Popular Tags |