/* See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* Esri Inc. licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.esri.gpt.server.assertion.index;
import com.esri.gpt.framework.util.Val;
import java.io.IOException;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.Term;
import org.apache.lucene.index.TermDocs;
import org.apache.lucene.search.DocIdSet;
import org.apache.lucene.search.Filter;
import org.apache.lucene.util.OpenBitSet;
/**
* A filter associated with a field and value.
*/
@SuppressWarnings("serial")
public class AsnFilter extends Filter {
/** class variables ========================================================= */
/** Chained and operand = "and" */
public static final String CHAINED_OPERAND_AND = "and";
/** Chained and not operand = "andnot" */
public static final String CHAINED_OPERAND_ANDNOT = "andnot";
/** Chained or operand = "or" */
public static final String CHAINED_OPERAND_OR = "or";
/** instance variables ====================================================== */
private AsnFilter[] chain;
private String chainedOperand;
private String fieldName;
private long timeMillis = 0;
private String value;
/** constructors ============================================================ */
/**
* Constructs with an associated field and value.
* @param fieldName the field name
* @param value the field name
*/
public AsnFilter(String fieldName,String value) {
this.fieldName = fieldName;
this.value = value;
}
/**
* Constructs with an associated field and value.
* @param chain chain
* @param chainedOperand operand
*/
public AsnFilter(AsnFilter[] chain, String chainedOperand) {
this.chain = chain;
this.chainedOperand = chainedOperand;
}
/** properties ============================================================== */
/**
* Gets the execution time.
* @return the execution time (in milliseconds)
*/
public long getTimeMillis() {
return this.timeMillis;
}
/**
* Sets the execution time.
* @param millis the execution time (in milliseconds)
*/
protected void setTimeMillis(long millis) {
this.timeMillis = millis;
}
/** methods ================================================================= */
/**
* Applies the filter and returns a DocIdSet of matching documents.
* @param reader the index reader
* @return the DocIdSet the matching documents
* @throws IOException if an exception is encountered while reading the index
*/
public DocIdSet getDocIdSet(IndexReader reader) throws IOException {
long t1 = System.currentTimeMillis();
OpenBitSet bitSet = null;
if (this.chain == null) {
bitSet = this.queryValue(reader);
} else {
String operand = Val.chkStr(this.chainedOperand);
bitSet = new OpenBitSet(reader.maxDoc());
for (int i=0; i<this.chain.length; i++) {
AsnFilter asnFilter = this.chain[i];
if (i == 0) {
bitSet = (OpenBitSet)asnFilter.getDocIdSet(reader);
} else {
OpenBitSet subBitSet = (OpenBitSet)asnFilter.getDocIdSet(reader);
if (operand.equalsIgnoreCase(AsnFilter.CHAINED_OPERAND_AND)) {
if (bitSet.cardinality() > 0) {
bitSet.and(subBitSet);
}
} else if (operand.equalsIgnoreCase(AsnFilter.CHAINED_OPERAND_OR)) {
bitSet.or(subBitSet);
} else if (operand.equalsIgnoreCase(AsnFilter.CHAINED_OPERAND_ANDNOT)) {
if (bitSet.cardinality() > 0) {
bitSet.andNot(subBitSet);
}
} else {
if (bitSet.cardinality() > 0) {
bitSet.and(subBitSet);
}
}
}
}
}
setTimeMillis(System.currentTimeMillis() - t1);
return bitSet;
}
/**
* Queries for documents that match the supplied value.
* @param reader the index reader
* @return the OpenBitSet (documents with matches are set to true)
* @throws IOException if an exception is encountered while reading the index
*/
private OpenBitSet queryValue(IndexReader reader) throws IOException {
OpenBitSet bitSet = new OpenBitSet(reader.maxDoc());
if ((this.value != null) && (this.value.length() > 0)) {
TermDocs termDocs = null;
try {
Term term = new Term(this.fieldName,this.value);
termDocs = reader.termDocs();
termDocs.seek(term);
while (termDocs.next()) {
bitSet.set(termDocs.doc());
}
} finally {
try {if (termDocs != null) termDocs.close();} catch (Exception ef) {}
}
}
return bitSet;
}
}