/**
*
*/
package org.openntf.domino.big.impl;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.logging.Logger;
import org.openntf.domino.big.IndexDatabase;
/**
* @author Nathan T. Freeman
*
*/
public class IndexQuery {
@SuppressWarnings("unused")
private static final Logger log_ = Logger.getLogger(IndexQuery.class.getName());
private Set<CharSequence> terms_;
private Set<CharSequence> dbids_;
private Set<CharSequence> items_;
private Set<CharSequence> forms_;
private boolean isAnd_ = false;
private int limit_ = 0;
@SuppressWarnings("unused")
private transient IndexResults results_;
public IndexQuery() {
}
public void setLimit(final int limit) {
limit_ = limit;
}
public int getLimit() {
return limit_;
}
public void setAnd(final boolean value) {
isAnd_ = value;
}
public boolean isAnd() {
return isAnd_;
}
/**
* @return the terms
*/
public Set<CharSequence> getTerms() {
return terms_;
}
/**
* @param terms
* the terms to set
*/
public void setTerms(final java.util.Collection<?> terms) {
terms_ = IndexDatabase.Utils.toStringSet(terms);
}
public void setStringTerms(final Set<CharSequence> terms) {
terms_ = terms;
}
public void setMergedTerms(final String terms) {
Set<String> set = new HashSet<String>();
if (terms.indexOf(' ') > 0) {
String[] strings = terms.split(" ");
for (String str : strings) {
set.add(str);
}
} else {
set.add(terms);
}
setTerms(set);
}
public void setMergedTerms(final CharSequence terms, final String split) {
Set<CharSequence> set = new HashSet<CharSequence>();
String[] strings = terms.toString().split(split);
// System.out.println("Setting up " + strings.length + " terms");
for (String str : strings) {
set.add(str);
}
setStringTerms(set);
}
public void setTerms(final CharSequence term) {
terms_ = IndexDatabase.Utils.toStringSet(term);
}
/**
* @return the dbids
*/
public Set<CharSequence> getDbids() {
return dbids_;
}
/**
* @param dbids
* the dbids to set
*/
public void setDbids(final Collection<Object> dbids) {
dbids_ = IndexDatabase.Utils.toStringSet(dbids);
if (dbids != null && !dbids.isEmpty()) {
// System.out.println("Setting dbids filter to " + dbids.getClass().getSimpleName() + " of size " + dbids.size() + ": "
// + debugStringSet(dbids_));
}
}
/**
* @return the items
*/
public Set<CharSequence> getItems() {
return items_;
}
/**
* @param items
* the items to set
*/
public void setItems(final Collection<Object> items) {
items_ = IndexDatabase.Utils.toStringSet(items);
}
/**
* @return the forms
*/
public Set<CharSequence> getForms() {
return forms_;
}
/**
* @param forms
* the forms to set
*/
public void setForms(final Collection<Object> forms) {
forms_ = IndexDatabase.Utils.toStringSet(forms);
}
private static final boolean profile_ = true;
protected IndexResults createResultsFromHitList(final List<IndexHit> hits) {
return new IndexResults(hits);
}
// private static final List<IndexHit> emptyHits = new ArrayList<IndexHit>();
@SuppressWarnings("unused")
private static String debugStringSet(final Set<String> set) {
StringBuilder debug = new StringBuilder();
debug.append('[');
if (set == null || set.size() == 0) {
} else if (set.size() == 1) {
debug.append(set.iterator().next());
} else {
boolean isFirst = true;
for (String term : set) {
if (!isFirst) {
debug.append(" : ");
}
isFirst = false;
debug.append(term);
}
}
debug.append(']');
return debug.toString();
}
@SuppressWarnings("unused")
private String debugGetTerms() {
StringBuilder debug = new StringBuilder();
Set<CharSequence> terms = terms_;
debug.append('[');
if (terms == null || terms.size() == 0) {
} else if (terms.size() == 1) {
debug.append(terms.iterator().next());
} else {
boolean isFirst = true;
for (CharSequence term : terms) {
if (!isFirst) {
if (isAnd()) {
debug.append(" AND ");
} else {
debug.append(" OR ");
}
}
isFirst = false;
debug.append(term);
}
}
debug.append(']');
return debug.toString();
}
public IndexResults execute(final IndexDatabase db) {
long startNanos = 0;
if (profile_)
startNanos = System.nanoTime();
IndexResults result = null;
// System.out.println("Executing with: " + debugGetTerms());
Set<CharSequence> localTerms = getTerms();
if (!db.getCaseSensitive()) {
localTerms = IndexDatabase.Utils.toCISSet(localTerms);
}
if (isAnd() && localTerms.size() > 1) {
for (CharSequence term : localTerms) {
List<IndexHit> hits = db.getTermResults(term, getLimit(), getDbids(), IndexDatabase.Utils.toCISSet(getItems()), getForms());
if (result == null) {
result = createResultsFromHitList(hits);
} else {
IndexResults temp = createResultsFromHitList(hits);
result.intersect(temp);
}
}
} else {
result = createResultsFromHitList(new ArrayList<IndexHit>());
for (CharSequence term : localTerms) {
List<IndexHit> hits = db.getTermResults(term, getLimit(), getDbids(), IndexDatabase.Utils.toCISSet(getItems()), getForms());
IndexResults temp = createResultsFromHitList(hits);
result.merge(temp);
}
}
if (profile_) {
int resultCount = result == null ? 0 : result.getHits().size();
System.out
.println("IndexQuery executed for " + resultCount + " results in " + ((System.nanoTime() - startNanos) / 1000) + "us");
}
return result;
}
/* (non-Javadoc)
* @see java.io.Externalizable#readExternal(java.io.ObjectInput)
*/
public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException {
isAnd_ = in.readBoolean();
limit_ = in.readInt();
boolean hasTerms = in.readBoolean();
if (hasTerms) {
int termSize = in.readInt();
Set<String> terms_ = new HashSet<String>();
for (int i = 0; i < termSize; i++) {
terms_.add(in.readUTF());
}
}
boolean hasDbs = in.readBoolean();
if (hasDbs) {
int dbSize = in.readInt();
Set<String> dbids_ = new HashSet<String>();
for (int i = 0; i < dbSize; i++) {
dbids_.add(in.readUTF());
}
}
boolean hasForms = in.readBoolean();
if (hasForms) {
int formSize = in.readInt();
Set<String> forms_ = new HashSet<String>();
for (int i = 0; i < formSize; i++) {
forms_.add(in.readUTF());
}
}
boolean hasItems = in.readBoolean();
if (hasItems) {
int itemSize = in.readInt();
Set<String> items_ = new HashSet<String>();
for (int i = 0; i < itemSize; i++) {
items_.add(in.readUTF());
}
}
}
/* (non-Javadoc)
* @see java.io.Externalizable#writeExternal(java.io.ObjectOutput)
*/
public void writeExternal(final ObjectOutput out) throws IOException {
out.writeBoolean(isAnd_);
out.writeInt(limit_);
if (terms_ != null) {
out.writeBoolean(true);
out.writeInt(terms_.size());
for (CharSequence term : terms_) {
out.writeUTF(term.toString());
}
} else {
out.writeBoolean(false);
}
if (dbids_ != null) {
out.writeBoolean(true);
out.writeInt(dbids_.size());
for (CharSequence dbid : dbids_) {
out.writeUTF(dbid.toString());
}
} else {
out.writeBoolean(false);
}
if (forms_ != null) {
out.writeBoolean(true);
out.writeInt(forms_.size());
for (CharSequence form : forms_) {
out.writeUTF(form.toString());
}
} else {
out.writeBoolean(false);
}
if (items_ != null) {
out.writeBoolean(true);
out.writeInt(items_.size());
for (CharSequence item : items_) {
out.writeUTF(item.toString());
}
} else {
out.writeBoolean(false);
}
}
}