/*
* Copyright (C) 2004 Paul Browne, http://www.firstpartners.net,
* built with the help of Fast-Soft (fastsoftdev@yahoo.com)
*
* released under terms of the GPL license
* http://www.opensource.org/licenses/gpl-license.php
*
* This product includes software developed by the
* Apache Software Foundation (http://www.apache.org)."
*
* This product includes software developed by the
* Spring Framework Project (http://www.springframework.org)."
*
*/
package net.fp.rp.search.back.index;
import java.io.File;
import java.io.IOException;
import net.fp.rp.search.back.struct.DocumStruct;
import net.fp.rp.search.back.struct.TupleStruct;
import net.fp.rp.search.common.util.MessageUtil;
import net.fp.rp.search.plugins.IIndexManager;
import org.apache.log4j.Logger;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.Term;
import org.apache.lucene.index.TermEnum;
/**
* Basic IndexManager to allow adding / searching on a (Lucene based) Index.
*
* @author brownpa
* Copyright @link www.firstpartners.net/red
*/
public class BasicIndex implements IIndexManager {
/** Default document path */
static final String DEFAULT_DOCUM_PATH = "http://www.red-piranha.com";
/** Default document author */
static final String DEFAULT_DOCUM_AUTHOR = "Paul Browne";
/** Logger for this class and subclasses */
protected final Logger logger = Logger.getLogger(getClass());
/** Index root folder ${rp.root}/lucene */
private String root;
/** Flag to mark that index is in re-index process */
private boolean isReady = true;
/**
* Optimize the index (better results time for search process)
*/
public void optimize() {
synchronized (this) {
try {
IndexWriter iw = new IndexWriter(root, new StandardAnalyzer(),
false);
iw.optimize();
iw.close();
} catch (IOException e) {
logger.warn("Error occured in the optimize process of the index",
e);
}
}
}
/**
* Uupdate the calculated score of the document with the specified id
* Score is already calculated by the category manager = (old_calcscore+weight)*categoryscore
*
* @param id Document id
* @param score New score(categoryscore*calc_score) for the document
*/
public void reindex(final String id, final double score) {
synchronized (this) {
boolean foundit = false;
try {
//open the file
IndexWriter iw;
IndexReader ir = IndexReader.open(root);
int numDocs = ir.maxDoc();
for (int i = 0; (i < numDocs) && (!foundit); i++) {
if (!ir.isDeleted(i)) {
//get the document
Document d = ir.document(i);
if (d != null) {
String comp_id = d.get(DocumStruct.FIELD_DOCUMENTID);
if (comp_id.equalsIgnoreCase(id)) {
foundit = true;
//replace the document
ir.delete(i);
ir.close();
// open writer to add document once again
logger.info("REINDEXING Node.." + comp_id);
iw = new IndexWriter(root,
new StandardAnalyzer(), false);
d.removeField(DocumStruct.FIELD_SORT_SCORE);
d.add(Field.Text(DocumStruct.FIELD_SORT_SCORE,
Double.toString(score)));
iw.addDocument(d);
iw.close();
// reopen
ir = IndexReader.open(root);
}
} else {
ir.delete(i);
}
}
}
//close the reader
ir.close();
} catch (IOException e) {
}
}
}
/**
* Reindex the specified document
*
* @param document ID of the document to reindex
*/
public void addToIndex(Document document) {
//remove the document from the index
//removeFromIndex( document.get( DocumStruct.FIELD_DOCUMID));
logger.debug("Adding Document to index:"+document);
addDocToIndex(document);
}
/**
* Add the document to the index
*
* @param document
*/
private void addDocToIndex(Document document) {
//add the documents
synchronized (this) {
//open the file
IndexWriter iw = null;
try {
iw = new IndexWriter(root, new StandardAnalyzer(), false);
//add the new data to the index
iw.addDocument(document);
} catch (IOException e) {
} finally {
try {
if (iw != null) {
iw.close();
}
} catch (IOException e) {
logger.warn("Handling IOException",e);
}
}
}
}
/**
* Reindex of all the documents with the specified categoryname
*
* @param documentsToUpdate Name of the category to reindex
*/
public void update(final DocumStruct[] documentsToUpdate) {
synchronized (this) {
try {
//open the file
IndexWriter iw;
IndexReader ir = IndexReader.open(root);
int numDocs = ir.maxDoc();
for (int i = 0; i < numDocs; i++) {
if (!ir.isDeleted(i)) {
//get the document
Document d = ir.document(i);
if (d != null) {
String old_docid = d.get(DocumStruct.FIELD_DOCUMENTID);
boolean reindex = false;
//iterate on the category document lists
for (int j = 0;
(!reindex) &&
(j < documentsToUpdate.length); j++) {
if (old_docid.equals(
documentsToUpdate[j].getId())) {
reindex = true;
//replace the document
ir.delete(i);
ir.close();
// open writer to add document once again
logger.info("REINDEXING: " + old_docid);
iw = new IndexWriter(root,
new StandardAnalyzer(), false);
/*
d.removeField( DocumStruct.FIELD_CALCSCORE);
d.add( Field.Text(DocumStruct.FIELD_CALCSCORE,
String.valueOf(documentsToUpdate[j].getCalcScore())));
*/
iw.addDocument(d);
iw.close();
// reopen
ir = IndexReader.open(root);
} else {
//leave the document in the index
}
}
} else {
ir.delete(i);
}
}
}
//close the reader
ir.close();
} catch (IOException e) {
}
}
}
/**
* Remove the document from the index
*
* @param documentsToUpdate
*/
public void reindex(final Document[] documentsToUpdate) {
if (documentsToUpdate.length > 0) {
//remove from index
for (int i = 0; i < documentsToUpdate.length; i++) {
removeFromIndex(documentsToUpdate[i].get(
DocumStruct.FIELD_DOCUMENTID));
}
//add the documents
synchronized (this) {
//open the file
IndexWriter iw = null;
try {
iw = new IndexWriter(root, new StandardAnalyzer(), false);
//add the new data to the index
for (int i = 0; i < documentsToUpdate.length; i++) {
logger.info("REINDEXING: " +
documentsToUpdate[i].get(DocumStruct.FIELD_PATH));
iw.addDocument(documentsToUpdate[i]);
}
} catch (IOException e) {
} finally {
try {
if (iw != null) {
iw.close();
}
} catch (IOException e) {
}
}
}
}
}
/**
* Remove a piece of information from the index
*
* @param uniqueId
*/
public void removeFromIndex(String uniqueId) {
synchronized (this) {
IndexReader ir = null;
try {
ir = IndexReader.open(root);
logger.info("Unique document id " + uniqueId);
TermEnum uidterm = ir.terms(new Term(
DocumStruct.FIELD_DOCUMENTID, uniqueId));
while ((uidterm.term() != null) &&
(uidterm.term().field() == DocumStruct.FIELD_DOCUMENTID)) {
System.out.println("delete ...");
ir.delete(uidterm.term());
}
} catch (IOException e) {
} finally {
try {
if (ir != null) {
ir.close();
}
} catch (IOException e) {
}
}
}
}
/**
* Carry out any initiation tasks ( create the index folder and create an
* empty empty index if already not exists one
*/
public void onLoad() {
logger.info("IndexManager in onLoad process ");
//validate if the index folder is specified
File indexFolder = new File(root);
if (!indexFolder.exists()) {
logger.debug("Index Root :" + root +
" not exists -> create the folder ");
if (!indexFolder.mkdir()) {
logger.fatal(MessageUtil.getMessage(
"app.indexmanager.wrong.folder", new Object[] { root }));
return;
}
} else {
logger.debug("Index Root :" + root + " already exists ");
}
//validate if the index exists, if not create it
IndexReader ir = null;
try {
//clear the index
ir = IndexReader.open(root);
int numDocs = ir.maxDoc();
for (int i = 0; i < numDocs; i++) {
if (!ir.isDeleted(i)) {
//mark the document as deleted
ir.delete(i);
}
}
} catch (Exception e) {
logger.debug("Application Index does not exist, creating a new empty one",e);
try {
IndexWriter writer = new IndexWriter(root,
new StandardAnalyzer(), true);
//add a document to the index in order to sort the results
//link to red-piranha.com
DocumStruct doc = new DocumStruct();
doc.setTitle("");
doc.setPath(DEFAULT_DOCUM_PATH);
doc.setAuthor(DEFAULT_DOCUM_AUTHOR);
doc.addContentTuple(TupleStruct.KEYWORD_GENERIC, "");
//add the document to the index
writer.addDocument(doc.getIndexDocument());
writer.close();
} catch (IOException ex) {
logger.fatal(MessageUtil.getMessage(
"app.indexmanager.wrong.index", new Object[] { root }));
return;
}
} finally {
try {
if (ir != null) {
ir.close();
}
} catch (IOException e) {
}
}
logger.info("IndexManager finished the onload process");
}
/**
* Get the ready flag of the index
*
* @return Returns rue if the index is in running process, false otherwise
*/
public boolean isReady() {
return isReady;
}
/**
* Set the ready flag of the inddex
*
* @param isReady The isReady to set.
*/
public void setReady(boolean isReady) {
this.isReady = isReady;
}
/**
* Get the root index folder
*
* @return Returns the root index folder
*/
public String getRoot() {
return root;
}
/**
* Set the root index folder
*
* @param root The root to set.
*/
public void setRoot(String root) {
this.root = root;
}
}