001: package org.apache.lucene.search;
002:
003: /**
004: * Licensed to the Apache Software Foundation (ASF) under one or more
005: * contributor license agreements. See the NOTICE file distributed with
006: * this work for additional information regarding copyright ownership.
007: * The ASF licenses this file to You under the Apache License, Version 2.0
008: * (the "License"); you may not use this file except in compliance with
009: * the License. You may obtain a copy of the License at
010: *
011: * http://www.apache.org/licenses/LICENSE-2.0
012: *
013: * Unless required by applicable law or agreed to in writing, software
014: * distributed under the License is distributed on an "AS IS" BASIS,
015: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016: * See the License for the specific language governing permissions and
017: * limitations under the License.
018: */
019:
020: import java.io.IOException;
021: import java.util.Set;
022:
023: import org.apache.lucene.index.Term;
024: import org.apache.lucene.index.TermDocs;
025: import org.apache.lucene.index.IndexReader;
026: import org.apache.lucene.util.ToStringUtils;
027:
028: /** A Query that matches documents containing a term.
029: This may be combined with other terms with a {@link BooleanQuery}.
030: */
031: public class TermQuery extends Query {
032: private Term term;
033:
034: private class TermWeight implements Weight {
035: private Similarity similarity;
036: private float value;
037: private float idf;
038: private float queryNorm;
039: private float queryWeight;
040:
041: public TermWeight(Searcher searcher) throws IOException {
042: this .similarity = getSimilarity(searcher);
043: idf = similarity.idf(term, searcher); // compute idf
044: }
045:
046: public String toString() {
047: return "weight(" + TermQuery.this + ")";
048: }
049:
050: public Query getQuery() {
051: return TermQuery.this ;
052: }
053:
054: public float getValue() {
055: return value;
056: }
057:
058: public float sumOfSquaredWeights() {
059: queryWeight = idf * getBoost(); // compute query weight
060: return queryWeight * queryWeight; // square it
061: }
062:
063: public void normalize(float queryNorm) {
064: this .queryNorm = queryNorm;
065: queryWeight *= queryNorm; // normalize query weight
066: value = queryWeight * idf; // idf for document
067: }
068:
069: public Scorer scorer(IndexReader reader) throws IOException {
070: TermDocs termDocs = reader.termDocs(term);
071:
072: if (termDocs == null)
073: return null;
074:
075: return new TermScorer(this , termDocs, similarity, reader
076: .norms(term.field()));
077: }
078:
079: public Explanation explain(IndexReader reader, int doc)
080: throws IOException {
081:
082: ComplexExplanation result = new ComplexExplanation();
083: result.setDescription("weight(" + getQuery() + " in " + doc
084: + "), product of:");
085:
086: Explanation idfExpl = new Explanation(idf, "idf(docFreq="
087: + reader.docFreq(term) + ", numDocs="
088: + reader.numDocs() + ")");
089:
090: // explain query weight
091: Explanation queryExpl = new Explanation();
092: queryExpl.setDescription("queryWeight(" + getQuery()
093: + "), product of:");
094:
095: Explanation boostExpl = new Explanation(getBoost(), "boost");
096: if (getBoost() != 1.0f)
097: queryExpl.addDetail(boostExpl);
098: queryExpl.addDetail(idfExpl);
099:
100: Explanation queryNormExpl = new Explanation(queryNorm,
101: "queryNorm");
102: queryExpl.addDetail(queryNormExpl);
103:
104: queryExpl.setValue(boostExpl.getValue()
105: * idfExpl.getValue() * queryNormExpl.getValue());
106:
107: result.addDetail(queryExpl);
108:
109: // explain field weight
110: String field = term.field();
111: ComplexExplanation fieldExpl = new ComplexExplanation();
112: fieldExpl.setDescription("fieldWeight(" + term + " in "
113: + doc + "), product of:");
114:
115: Explanation tfExpl = scorer(reader).explain(doc);
116: fieldExpl.addDetail(tfExpl);
117: fieldExpl.addDetail(idfExpl);
118:
119: Explanation fieldNormExpl = new Explanation();
120: byte[] fieldNorms = reader.norms(field);
121: float fieldNorm = fieldNorms != null ? Similarity
122: .decodeNorm(fieldNorms[doc]) : 0.0f;
123: fieldNormExpl.setValue(fieldNorm);
124: fieldNormExpl.setDescription("fieldNorm(field=" + field
125: + ", doc=" + doc + ")");
126: fieldExpl.addDetail(fieldNormExpl);
127:
128: fieldExpl.setMatch(Boolean.valueOf(tfExpl.isMatch()));
129: fieldExpl.setValue(tfExpl.getValue() * idfExpl.getValue()
130: * fieldNormExpl.getValue());
131:
132: result.addDetail(fieldExpl);
133: result.setMatch(fieldExpl.getMatch());
134:
135: // combine them
136: result
137: .setValue(queryExpl.getValue()
138: * fieldExpl.getValue());
139:
140: if (queryExpl.getValue() == 1.0f)
141: return fieldExpl;
142:
143: return result;
144: }
145: }
146:
147: /** Constructs a query for the term <code>t</code>. */
148: public TermQuery(Term t) {
149: term = t;
150: }
151:
152: /** Returns the term of this query. */
153: public Term getTerm() {
154: return term;
155: }
156:
157: protected Weight createWeight(Searcher searcher) throws IOException {
158: return new TermWeight(searcher);
159: }
160:
161: public void extractTerms(Set terms) {
162: terms.add(getTerm());
163: }
164:
165: /** Prints a user-readable version of this query. */
166: public String toString(String field) {
167: StringBuffer buffer = new StringBuffer();
168: if (!term.field().equals(field)) {
169: buffer.append(term.field());
170: buffer.append(":");
171: }
172: buffer.append(term.text());
173: buffer.append(ToStringUtils.boost(getBoost()));
174: return buffer.toString();
175: }
176:
177: /** Returns true iff <code>o</code> is equal to this. */
178: public boolean equals(Object o) {
179: if (!(o instanceof TermQuery))
180: return false;
181: TermQuery other = (TermQuery) o;
182: return (this .getBoost() == other.getBoost())
183: && this .term.equals(other.term);
184: }
185:
186: /** Returns a hash code value for this object.*/
187: public int hashCode() {
188: return Float.floatToIntBits(getBoost()) ^ term.hashCode();
189: }
190:
191: }
|