package com.idega.block.websearch.presentation;
/**
* This class is a part of the websearch webcrawler and search engine block. <br>
* It is based on the <a href="http://lucene.apache.org">Lucene</a> java search engine from the Apache group and loosly <br>
* from the work of David Duddleston of i2a.com.<br>
*
* @copyright Idega Software 2002
* @author <a href="mailto:eiki@idega.is">Eirikur Hrafnsson</a>
*/
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import com.idega.idegaweb.*;
import com.idega.presentation.*;
import com.idega.presentation.text.*;
import com.idega.presentation.ui.*;
import com.idega.block.websearch.business.*;
import com.idega.block.websearch.data.*;
import com.idega.core.builder.data.ICPage;
public class WebSearcher extends Block {
private final static String IW_BUNDLE_IDENTIFIER = "com.idega.block.websearch";
private final static String SEARCH_PARAM = "iw_bl_ws_search";
private final static String CRAWL_PARAM = "iw_bl_ws_crawl";
private final static String CRAWL_REPORT_PARAM = "iw_bl_ws_cr_re";
private final static String HITS_PER_SET_PARAM = "iw_bl_ws_hi_p_s";
private final static String EXACT_PHRASE_PARAM = "iw_bl_ws_ex_ph";
private final static String PUBLISHED_FROM_PARAM = "iw_bl_ws_pb_fr";
private final static String DETAILED_PARAM = "iw_bl_ws_de";
private final static String DIRECTION_PARAM = "iw_bl_ws_set_dir";
private final static String HITS_ITERATOR_SESSION_PARAM = "iw_bl_ws_hitsiterator";
private final static String HITS_MAP_SESSION_PARAM = "iw_bl_ws_hitsmap";
private final static String INDEX_NO_REPORT = "0";
private final static String INDEX_MINOR_REPORT = "1";
private final static String INDEX_NORMAL_REPORT = "2";
private final static String INDEX_DETAILED_REPORT = "3";
private final static String DIRECTION_NEXT = "next";
private final static String DIRECTION_PREV = "prev";
private WebSearchIndex index;
private Crawler crawler;
private boolean showResults = false;
private boolean crawl = false;
private boolean exact = false;
private boolean detailed = false;
private boolean canEdit = false;
private boolean showOnlySearch = false;
private boolean showButtonsAsLinks = false;
private String queryString = null;
private String direction = null;
private Image searchImage = null;
private String searchWidth = null;
private Link titleLinkProto = new Link();
private Text contentTextProto = new Text();
private Text extraInfoTextProto = new Text();
private String contentTextProtoStyle = null;
private String extraInfoTextProtoStyle = null;
private String titleLinkProtoStyle = null;
private int hitsPerSet = 10;
private int publishedFromDays = 0;
private int report = 0;
private IWBundle iwb = null;
private IWResourceBundle iwrb = null;
private static final int VERTICAL_LAYOUT = 1;
private static final int HORIZONTAL_LAYOUT = 2;
private int layout = HORIZONTAL_LAYOUT;
private String searchStyleClass;
private String arrowStyleClass;
private ICPage submitPage;
private String inputStyle;
private String inputWidth;
private int spaceBetween = 3;
private Collection ignoreParameters;
public WebSearcher() {
}
public String getBundleIdentifier() {
return IW_BUNDLE_IDENTIFIER;
}
private void parseAction(IWContext iwc) {
if (iwc.isParameterSet(SEARCH_PARAM)) {
this.showResults = true;
this.queryString = iwc.getParameter(SEARCH_PARAM);
this.exact = iwc.isParameterSet(EXACT_PHRASE_PARAM);
this.detailed = iwc.isParameterSet(DETAILED_PARAM);
String fromDays = iwc.getParameter(PUBLISHED_FROM_PARAM);
if (fromDays != null) {
this.publishedFromDays = Integer.parseInt(fromDays);
}
String perSet = iwc.getParameter(HITS_PER_SET_PARAM);
if (perSet != null) {
this.hitsPerSet = Integer.parseInt(perSet);
}
this.direction = iwc.getParameter(DIRECTION_PARAM);
}
else if (iwc.isParameterSet(CRAWL_PARAM)) {
this.crawl = true;
String sReport = iwc.getParameter(CRAWL_REPORT_PARAM);
if (sReport != null) {
this.report = Integer.parseInt(sReport);
}
}
if (this.showOnlySearch) {
this.showResults = false;
}
this.canEdit = this.hasEditPermission();
}
/**
* @see com.idega.presentation.PresentationObject#main(IWContext)
*/
public void main(IWContext iwc) throws Exception {
this.iwb = getBundle(iwc);
this.iwrb = getResourceBundle(iwc);
parseAction(iwc);
if (this.showResults) {
prepStyles();
search(iwc);
}
else if (this.crawl) {
iwc.removeSessionAttribute(HITS_MAP_SESSION_PARAM);
crawl();
}
else {
add(getSearchForm());
}
}
private void crawl() throws Exception {
add(this.iwrb.getLocalizedString("indexing", "Indexing..."));
addBreak();
this.index = WebSearchManager.getIndex("main"); //this should not be hard coded
if (this.report > 0) {
this.crawler = new Crawler(this.index, this.report); //change so that crawler return an arraylist and then print that or something
}
else { //no report
this.crawler = new Crawler(this.index);
}
this.crawler.addIgnoreParameters(this.ignoreParameters);
this.crawler.crawl();
addBreak();
add(this.iwrb.getLocalizedString("done", "Done!"));
addBreak();
add(new BackButton(this.iwrb.getLocalizedString("back", "back")));
}
private Form getSearchForm() {
Form searchForm = new Form();
if (this.submitPage != null) {
searchForm.setPageToSubmitTo(this.submitPage);
}
Table table = new Table();
table.setCellpadding(0);
table.setCellspacing(0);
if (this.searchWidth != null) {
table.setWidth(this.searchWidth);
}
TextInput search = new TextInput(SEARCH_PARAM);
if (this.queryString != null) {
search.setContent(this.queryString);
}
else {
search.setContent(this.iwrb.getLocalizedString("search_entire_site", "Search entire site"));
search.setOnFocus("this.value=''");
}
if (this.inputStyle != null) {
search.setStyleAttribute(this.inputStyle);
}
if (this.inputWidth != null) {
search.setWidth(this.inputWidth);
}
Link crawl = null;
if (this.canEdit) {
crawl = new Link(this.iwrb.getLocalizedString("index.this.site", "Index this site (done every 24h)"));
crawl.addParameter(CRAWL_PARAM, "true");
crawl.addParameter(CRAWL_REPORT_PARAM, INDEX_NORMAL_REPORT);
}
if (this.layout == HORIZONTAL_LAYOUT) {
table.setCellpadding(3);
table.add(search, 1, 1);
if (!this.showButtonsAsLinks) {
SubmitButton button = null;
if (this.searchImage != null) {
button = new SubmitButton(this.searchImage);
}
else {
button = new SubmitButton(this.iwrb.getLocalizedString("search", "Search"));
}
table.add(button, 2, 1);
}
else {
Link link = new Link(this.iwrb.getLocalizedString("search", "Search"));
link.setToFormSubmit(searchForm);
if (this.searchStyleClass != null) {
link.setStyle(this.searchStyleClass);
}
table.add(link, 2, 1);
}
if (crawl != null) {
table.mergeCells(1, 2, 2, 2);
table.add(crawl, 2, 2);
}
}
else if (this.layout == VERTICAL_LAYOUT) {
table.add(search, 1, 1);
table.setHeight(2, this.spaceBetween);
Link link = new Link(this.iwrb.getLocalizedString("search", "Search"));
link.setToFormSubmit(searchForm);
if (this.searchStyleClass != null) {
link.setStyle(this.searchStyleClass);
}
Link arrow = new Link(">>");
arrow.setToFormSubmit(searchForm);
if (this.arrowStyleClass != null) {
arrow.setStyle(this.arrowStyleClass);
}
table.add(link, 1, 3);
table.add(Text.NON_BREAKING_SPACE, 1, 3);
table.add(arrow, 1, 3);
if (crawl != null) {
table.setHeight(4, 6);
table.add(crawl, 1, 5);
}
}
searchForm.add(table);
return searchForm;
}
private void search(IWContext iwc) {
add(getSearchForm());
addBreak();
WebSearchHitIterator hits = getHitsFromSession(iwc,HITS_ITERATOR_SESSION_PARAM + this.queryString);
if (hits == null) {
try {
com.idega.block.websearch.business.WebSearcher searcher = new com.idega.block.websearch.business.WebSearcher(WebSearchManager.getIndex("main"));
//hits per page
searcher.setHitsPerSet(this.hitsPerSet);
// exact phrase
searcher.setPhraseSearch(this.exact);
// from days
if (this.publishedFromDays > 0) {
searcher.setFromDays(this.publishedFromDays);
}
hits = searcher.search(this.queryString);
setHitsToSession(iwc,HITS_ITERATOR_SESSION_PARAM + this.queryString, hits);
}
catch (Exception e) {
e.printStackTrace();
add(this.iwrb.getLocalizedString("you.have.to.index.first", "You need to run the indexer first!"));
}
}
if(hits!=null) {
addBreak();
add(getResultSetInfo(hits));
addBreak();
Table results = new Table();
results.setWidth(Table.HUNDRED_PERCENT);
//results.setHeight(Table.HUNDRED_PERCENT);
results.setCellpaddingAndCellspacing(0);
int row = 1;
int row2 = 1;
while (hits.hasNextInSet()) {
WebSearchHit hit = hits.next();
//String bgColor = (hit.getRank()%2==0)?"#BBBBBB":"#CDCDCD";
Table hitTable = new Table(1, 3);
hitTable.setWidth(Table.HUNDRED_PERCENT);
hitTable.setHeight(50);
hitTable.setCellpadding(0);
hitTable.setCellspacing(1);
//hitTable.setColor(bgColor);
//if detailed ?
//hitTable.add(new Text("Score: "+hit.getScore()),1,row++);
//hitTable.add(new Text("Published: "+ hit.getPublishedFormated()),1,row++);
//hitTable.add(new Text("Content Type: "+hit.getContentType()),1,row++);
//hitTable.add(new Text("Keywords: "+hit.getKeywords()),1,row++); veit ekki afhverju thetta skilar alltaf null !?
//hitTable.add(new Text("Categories: "+hit.getCategories()),1,row++);
//hitTable.add(new Text("Description: "+hit.getDescription()),1,row++);
Link title = (Link) this.titleLinkProto.clone();
title.setURL(hit.getURL());
String sTitle = hit.getTitle();
if (sTitle == null) {
sTitle = this.iwrb.getLocalizedString("websearch.untitled", "Untitled");
}
else if (sTitle.equals("null")) {
sTitle = this.iwrb.getLocalizedString("websearch.untitled", "Untitled");
}
title.setText(sTitle);
hitTable.add(title, 1, row++);
String contents = hit.getContents(this.queryString); //could be heavy....
if (contents != null) {
contents = "..." + contents + "...";
Text contentsText = (Text) this.contentTextProto.clone();
contentsText.setText(contents);
hitTable.add(contentsText, 1, row++);
}
String extraInfo = hit.getHREF() + " - " + hit.getContentType() + " - " + this.iwrb.getLocalizedString("rank", "rank") + ": " + hit.getRank();
Text extraInfoText = (Text) this.extraInfoTextProto.clone();
extraInfoText.setText(extraInfo);
hitTable.add(extraInfoText, 1, row);
row = 1;
results.add(hitTable, 1, row2++);
results.add(Text.getBreak(), 1, row2++);
}
add(results);
}
}
private void prepStyles() {
if (this.contentTextProtoStyle != null) {
this.contentTextProto.setFontStyle(this.contentTextProtoStyle);
}
else {
this.contentTextProto.setFontFace(Text.FONT_FACE_ARIAL);
this.contentTextProto.setFontSize(Text.FONT_SIZE_10_HTML_2);
}
if (this.extraInfoTextProtoStyle != null) {
this.extraInfoTextProto.setFontStyle(this.extraInfoTextProtoStyle);
}
else {
this.extraInfoTextProto.setFontFace(Text.FONT_FACE_ARIAL);
this.extraInfoTextProto.setFontSize(Text.FONT_SIZE_10_HTML_2);
this.extraInfoTextProto.setFontColor("#008000");
}
if (this.titleLinkProtoStyle != null) {
this.titleLinkProto.setFontStyle(this.titleLinkProtoStyle);
}
else {
this.titleLinkProto.setFontSize(Text.FONT_SIZE_12_HTML_3);
this.titleLinkProto.setFontColor("#0000CC");
}
}
private Table getResultSetInfo(WebSearchHitIterator hits) {
//temporary html tags inline and need to localize
Table info = new Table();
info.setWidth(Table.HUNDRED_PERCENT);
info.setColor("#3366cc");
// Get Set by direction
if (this.direction != null && this.direction.equals(DIRECTION_NEXT)) {
hits.nextSet();
}
if (this.direction != null && this.direction.equals(DIRECTION_PREV)) {
hits.previousSet();
}
Text textProto = new Text();
textProto.setFontColor("#FFFFFF");
textProto.setFontFace(Text.FONT_FACE_ARIAL);
textProto.setFontSize(Text.FONT_SIZE_10_HTML_2);
Text text1 = (Text) textProto.clone();
Text text2 = (Text) textProto.clone();
Text text3 = (Text) textProto.clone();
text1.setText(this.iwrb.getLocalizedString("searched.for", "Searched for") + " : <b>" + hits.getQuery() + "</b>. " + this.iwrb.getLocalizedString("results", "Results") + " ");
info.add(text1, 1, 1);
if (hits.hasPreviousSet()) {
Link prev = new Link("<< ");
prev.addParameter(DIRECTION_PARAM, DIRECTION_PREV);
prev.addParameter(SEARCH_PARAM, this.queryString);
prev.setFontColor("#FFFFFF");
prev.setFontFace(Text.FONT_FACE_ARIAL);
prev.setFontSize(Text.FONT_SIZE_10_HTML_2);
prev.setBold();
info.add(prev, 1, 1);
}
text2.setText("<b>" + hits.getSetStartPosition() + " - " + hits.getSetEndPosition() + "</b>");
info.add(text2, 1, 1);
if (hits.hasNextSet()) {
Link next = new Link(" >> ");
next.addParameter(DIRECTION_PARAM, DIRECTION_NEXT);
next.addParameter(SEARCH_PARAM, this.queryString);
next.setFontColor("#FFFFFF");
next.setFontFace(Text.FONT_FACE_ARIAL);
next.setFontSize(Text.FONT_SIZE_10_HTML_2);
next.setBold();
info.add(next, 1, 1);
}
text3.setText(" " + this.iwrb.getLocalizedString("of", "of") + " <b>" + hits.getTotalHits() + "</b>" + ".");
info.add(text3, 1, 1);
return info;
}
public void setContentTextStyle(String style) {
this.contentTextProtoStyle = style;
}
public void setExtraInfoTextStyle(String style) {
this.extraInfoTextProtoStyle = style;
}
public void setTitleLinkStyle(String style) {
this.titleLinkProtoStyle = style;
}
private Map getSessionMap(IWContext iwc) {
Map sessionMap = (Map) iwc.getSessionAttribute(HITS_MAP_SESSION_PARAM);
if (sessionMap == null) {
sessionMap = new HashMap();
iwc.setSessionAttribute(HITS_MAP_SESSION_PARAM, sessionMap);
}
return sessionMap;
}
private WebSearchHitIterator getHitsFromSession(IWContext iwc, String value) {
return (WebSearchHitIterator) getSessionMap(iwc).get(value);
}
private void setHitsToSession(IWContext iwc, String value, WebSearchHitIterator wshi) {
getSessionMap(iwc).put(value,wshi);
}
/**
* @param showOnlySearch The showOnlySearch to set.
*/
public void setShowOnlySearch(boolean showOnlySearch) {
this.showOnlySearch = showOnlySearch;
}
/**
* @param arrowStyleClass The arrowStyleClass to set.
*/
public void setArrowStyleClass(String arrowStyleClass) {
this.arrowStyleClass = arrowStyleClass;
}
/**
* @param inputStyle The inputStyle to set.
*/
public void setInputStyle(String inputStyle) {
this.inputStyle = inputStyle;
}
/**
* @param searchStyleClass The searchStyleClass to set.
*/
public void setSearchStyleClass(String searchStyleClass) {
this.searchStyleClass = searchStyleClass;
}
/**
* @param submitPage The submitPage to set.
*/
public void setSubmitPage(ICPage submitPage) {
this.submitPage = submitPage;
}
public void setVerticalLayout(boolean vertical) {
if (vertical) {
this.layout = VERTICAL_LAYOUT;
}
else {
this.layout = HORIZONTAL_LAYOUT;
}
}
/**
* @param inputWidth The inputWidth to set.
*/
public void setInputWidth(String inputWidth) {
this.inputWidth = inputWidth;
}
/**
* @param spaceBetween The spaceBetween to set.
*/
public void setSpaceBetween(int spaceBetween) {
this.spaceBetween = spaceBetween;
}
public void setParameterToIgnore(String parameter) {
if (this.ignoreParameters == null) {
this.ignoreParameters = new ArrayList();
}
this.ignoreParameters.add(parameter);
}
public void setShowButtonsAsLinks(boolean showButtonsAsLinks) {
this.showButtonsAsLinks = showButtonsAsLinks;
}
public void setSearchImage(Image searchImage) {
this.searchImage = searchImage;
}
public void setSearchWidth(String searchWidth) {
this.searchWidth = searchWidth;
}
}