/*
* Created on May 2, 2004
*/
package com.openedit.modules.search;
import java.io.IOException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.apache.lucene.document.DateTools;
import org.apache.lucene.document.Document;
import org.apache.lucene.search.Hits;
import com.openedit.OpenEditRuntimeException;
import com.openedit.hittracker.HitTracker;
import com.openedit.hittracker.Term;
/**
* @author cburkey
*
*/
public class LuceneHitTracker extends HitTracker {
protected Hits fieldHits;
protected Map fieldFormaters;
public LuceneHitTracker() {
}
public LuceneHitTracker(Hits inHits) {
setHits(inHits);
}
public Hits getHits() {
return fieldHits;
}
public void setHits(Hits inHits) {
fieldHits = inHits;
}
public int getTotal() {
if (getHits() == null) {
return 0;
} else {
return getHits().length();
}
}
public Object get(int count) {
try {
return getHits().doc(count);
} catch (IOException ex) {
throw new OpenEditRuntimeException(ex);
}
}
public Iterator getAllHits() {
return new HitIterator(getHits());
}
public String toDateTime(String inValue) {
return toDateTime(inValue, null);
}
public String toDate(String inValue) {
return toDate(inValue, null);
}
public String toDate(String inValue, String inFormat) {
if (inValue == null) {
return null;
}
Date date = null;
try {
date = DateTools.stringToDate(inValue);
} catch (ParseException ex) {
throw new OpenEditRuntimeException(ex);
}
DateFormat format = null;
if( inFormat == null)
{
format = SimpleDateFormat.getDateInstance(SimpleDateFormat.SHORT);
}
else
{
format = (DateFormat)getFormaters().get(inFormat);
if( format == null)
{
format = new SimpleDateFormat(inFormat);
getFormaters().put(inFormat,format);
}
}
return format.format(date);
}
public String toDateTime(String inValue, String inFormat) {
if (inValue == null) {
return null;
}
Date date = null;
try {
date = DateTools.stringToDate(inValue);
} catch (ParseException ex) {
throw new OpenEditRuntimeException(ex);
}
DateFormat format = null;
if( inFormat == null)
{
format = SimpleDateFormat.getDateTimeInstance(SimpleDateFormat.SHORT,SimpleDateFormat.SHORT);
}
else
{
format = (DateFormat)getFormaters().get(inFormat);
if( format == null)
{
format = new SimpleDateFormat(inFormat);
getFormaters().put(inFormat,format);
}
}
return format.format(date);
}
public Integer findSelf(String inId) throws Exception {
if (inId == null) {
return null;
}
for (int i = 0; i < getTotal(); i++) {
Document hit = (Document) get(i);
if (inId.equals(hit.get("id"))) {
return new Integer(i);
}
}
return null;
}
public String previousId(String inId) throws Exception {
Integer row = findSelf(inId);
if (row != null && row.intValue() - 1 >= 0) {
Document hit = (Document) get(row.intValue() - 1);
return hit.get("id");
}
return null;
}
public String nextId(String inId) throws Exception {
Integer row = findSelf(inId);
if (row != null && row.intValue() + 1 < getTotal()) {
Document hit = (Document) get(row.intValue() + 1);
return hit.get("id");
}
return null;
}
public boolean contains(Object inHit) {
for (int i = 0; i < getTotal(); i++) {
Document hit = (Document) get(i);
if (hit.equals(inHit)) {
return true;
}
}
return false;
}
public String highlight(Object inDoc, String inField) {
Document doc = (Document) inDoc;
String value = doc.get(inField);
if (value != null) {
for (Iterator iterator = getSearchQuery().getTerms().iterator(); iterator
.hasNext();) {
Term term = (Term) iterator.next();
if (term.getValue() != null) {
value = replaceAll(value, term.getValue(),
"<span class='hit'>", "</span>");
}
}
}
value = trim(value, 300);
return value;
// String FIELD_NAME = "text";
// Highlighter highlighter = new Highlighter(new MyBolder(),
// new QueryScorer(query));
// highlighter.setTextFragmenter(new SimpleFragmenter(20));
// for (int i = 0; i < hits.length(); i++) {
// System.out.println("URL " + (i + 1) + ": " +
// hits.doc(i).getField("URL").stringValue());
// String text = hits.doc(i).get(FIELD_NAME);
// int maxNumFragmentsRequired = 2;
// String fragmentSeparator = "...";
// TokenStream tokenStream =
// analyzer.tokenStream(FIELD_NAME, new StringReader(text));
//
// String result =
// highlighter.getBestFragments(
// tokenStream,
// text,
// maxNumFragmentsRequired,
// fragmentSeparator);
// System.out.println("\t" + result);
}
private String replaceAll(String inSource, String inFind,
String inPreReplace, String inPostReplace) {
String lowercase = inSource.toLowerCase();
String findlower = inFind.toLowerCase();
StringBuffer buffer = new StringBuffer();
int start = 0;
while (true) {
int hit = lowercase.indexOf(findlower, start);
if (hit == -1) {
buffer.append(inSource.substring(start, inSource.length()));
break;
}
String before = inSource.substring(start, hit);
buffer.append(before);
buffer.append(inPreReplace);
String existing = inSource.substring(hit, hit + findlower.length());
buffer.append(existing);
buffer.append(inPostReplace);
start = hit + findlower.length();
}
return buffer.toString();
}
public String trim(String value, int inMax) {
StringBuffer result = new StringBuffer();
if (value.length() > inMax) {
// trim the begining
int start = value.indexOf("<span class='hit'>");
if (start > -1 && start > 10 && start + 150 < value.length()) {
int before = value.indexOf(" ", start - 10);
if (before < start) {
// result.append("..");
value = value.substring(before, value.length());
} else {
}
// TODO: Look for needed <span class='res'>
}
// if still too long trim the end
if (value.length() > inMax) {
int end = inMax;
// Near max distance.
for (; end > 0; end--) {
if (value.charAt(end) == ' ') {
break;
}
}
value = value.substring(0, end);
if (value.endsWith("<span")) {
value = value.substring(0, value.length() - 5);
}
}
// TODO: check for the need for </span>
}
return value;
}
public Map getFormaters()
{
if( fieldFormaters == null)
{
fieldFormaters = new HashMap(2);
}
return fieldFormaters;
}
public void setFormaters(Map inFormaters)
{
fieldFormaters = inFormaters;
}
public String getValue(Object inHit, String inKey)
{
Document doc = (Document)inHit;
return doc.get(inKey);
}
}
|