001: /**
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */package org.apache.solr.search;
017:
018: import org.apache.solr.util.OpenBitSet;
019: import org.apache.solr.util.BitSetIterator;
020:
021: /**
022: * <code>BitDocSet</code> represents an unordered set of Lucene Document Ids
023: * using a BitSet. A set bit represents inclusion in the set for that document.
024: *
025: * @author yonik
026: * @version $Id: BitDocSet.java 498246 2007-01-21 05:46:31Z yonik $
027: * @since solr 0.9
028: */
029: public class BitDocSet extends DocSetBase {
030: final OpenBitSet bits;
031: int size; // number of docs in the set (cached for perf)
032:
033: public BitDocSet() {
034: bits = new OpenBitSet();
035: }
036:
037: /** Construct a BitDocSet.
038: * The capacity of the OpenBitSet should be at least maxDoc() */
039: public BitDocSet(OpenBitSet bits) {
040: this .bits = bits;
041: size = -1;
042: }
043:
044: /** Construct a BitDocSet, and provides the number of set bits.
045: * The capacity of the OpenBitSet should be at least maxDoc()
046: */
047: public BitDocSet(OpenBitSet bits, int size) {
048: this .bits = bits;
049: this .size = size;
050: }
051:
052: /*** DocIterator using nextSetBit()
053: public DocIterator iterator() {
054: return new DocIterator() {
055: int pos=bits.nextSetBit(0);
056: public boolean hasNext() {
057: return pos>=0;
058: }
059:
060: public Integer next() {
061: return nextDoc();
062: }
063:
064: public void remove() {
065: bits.clear(pos);
066: }
067:
068: public int nextDoc() {
069: int old=pos;
070: pos=bits.nextSetBit(old+1);
071: return old;
072: }
073:
074: public float score() {
075: return 0.0f;
076: }
077: };
078: }
079: ***/
080:
081: public DocIterator iterator() {
082: return new DocIterator() {
083: private final BitSetIterator iter = new BitSetIterator(bits);
084: private int pos = iter.next();
085:
086: public boolean hasNext() {
087: return pos >= 0;
088: }
089:
090: public Integer next() {
091: return nextDoc();
092: }
093:
094: public void remove() {
095: bits.clear(pos);
096: }
097:
098: public int nextDoc() {
099: int old = pos;
100: pos = iter.next();
101: return old;
102: }
103:
104: public float score() {
105: return 0.0f;
106: }
107: };
108: }
109:
110: /**
111: *
112: * @return the <b>internal</b> OpenBitSet that should <b>not</b> be modified.
113: */
114: public OpenBitSet getBits() {
115: return bits;
116: }
117:
118: public void add(int doc) {
119: bits.set(doc);
120: size = -1; // invalidate size
121: }
122:
123: public void addUnique(int doc) {
124: bits.set(doc);
125: size = -1; // invalidate size
126: }
127:
128: public int size() {
129: if (size != -1)
130: return size;
131: return size = (int) bits.cardinality();
132: }
133:
134: /**
135: * The number of set bits - size - is cached. If the bitset is changed externally,
136: * this method should be used to invalidate the previously cached size.
137: */
138: public void invalidateSize() {
139: size = -1;
140: }
141:
142: public boolean exists(int doc) {
143: return bits.get(doc);
144: }
145:
146: @Override
147: public int intersectionSize(DocSet other) {
148: if (other instanceof BitDocSet) {
149: return (int) OpenBitSet.intersectionCount(this .bits,
150: ((BitDocSet) other).bits);
151: } else {
152: // they had better not call us back!
153: return other.intersectionSize(this );
154: }
155: }
156:
157: @Override
158: public int unionSize(DocSet other) {
159: if (other instanceof BitDocSet) {
160: // if we don't know our current size, this is faster than
161: // size + other.size - intersection_size
162: return (int) OpenBitSet.unionCount(this .bits,
163: ((BitDocSet) other).bits);
164: } else {
165: // they had better not call us back!
166: return other.unionSize(this );
167: }
168: }
169:
170: @Override
171: public int andNotSize(DocSet other) {
172: if (other instanceof BitDocSet) {
173: // if we don't know our current size, this is faster than
174: // size - intersection_size
175: return (int) OpenBitSet.andNotCount(this .bits,
176: ((BitDocSet) other).bits);
177: } else {
178: return super .andNotSize(other);
179: }
180: }
181:
182: @Override
183: public DocSet andNot(DocSet other) {
184: OpenBitSet newbits = (OpenBitSet) (bits.clone());
185: if (other instanceof OpenBitSet) {
186: newbits.andNot(((BitDocSet) other).bits);
187: } else {
188: DocIterator iter = other.iterator();
189: while (iter.hasNext())
190: newbits.clear(iter.nextDoc());
191: }
192: return new BitDocSet(newbits);
193: }
194:
195: @Override
196: public DocSet union(DocSet other) {
197: OpenBitSet newbits = (OpenBitSet) (bits.clone());
198: if (other instanceof BitDocSet) {
199: newbits.union(((BitDocSet) other).bits);
200: } else {
201: DocIterator iter = other.iterator();
202: while (iter.hasNext())
203: newbits.set(iter.nextDoc());
204: }
205: return new BitDocSet(newbits);
206: }
207:
208: public long memSize() {
209: return (bits.getBits().length << 3) + 16;
210: }
211: }
|