package org.sf.mustru.ui;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.InvocationTargetException;
import java.util.LinkedList;
import org.apache.log4j.PropertyConfigurator;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.ActionContributionItem;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.action.ToolBarManager;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.ProgressBar;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.jface.dialogs.IInputValidator;
import org.eclipse.jface.dialogs.InputDialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.window.ApplicationWindow;
import org.eclipse.jface.window.Window;
import org.eclipse.jface.wizard.WizardDialog;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.sf.mustru.crawl.CrawlConfig;
import org.sf.mustru.search.SearchQuery;
import org.sf.mustru.search.SearchQuestion;
import org.sf.mustru.utils.Constants;
import org.sf.mustru.utils.DbTools;
/**
* Display the main menu to create, run, and view the results of a crawl.
*/
public class OnlineIndex extends ApplicationWindow
{
public Color backYellow, backWhite, frontBlue, frontRed; //*-- a few colors
public Table table; //*-- multi-purpose table to show results of actions
public TableColumn tcol1, tcol2; //*-- two columns of the table
public String question = ""; //*-- the last question asked
public String query = ""; //*-- the last search engine query submitted
public String[] args; //*-- command line arguments
public static final IInputValidator iv = new IInputValidator() { public String isValid(String text) { return null; } };
private RunQAStartup rq = null; //*-- class to load the QA system
//*-- action for a new crawl
public String iconNew = Constants.MUSTRU_HOME + File.separator + "icons" + File.separator + "document-new.png";
public Action actionNew = new Action( "&New", ImageDescriptor.createFromFile(null, iconNew) )
{ public void run()
{ CrawlConfigWizard wizard = new CrawlConfigWizard(true);
WizardDialog wd = new WizardDialog( getShell(), wizard);
wd.setBlockOnOpen(true); wd.open();
}
};
//*-- action to edit a crawl
public String iconEdit = Constants.MUSTRU_HOME + File.separator + "icons" + File.separator + "document-open.png";
public Action actionEdit = new Action( "&Edit", ImageDescriptor.createFromFile(null, iconEdit))
{ public void run()
{ CrawlConfigWizard wizard = new CrawlConfigWizard(false);
WizardDialog wd = new WizardDialog( getShell(), wizard);
wd.setBlockOnOpen(true); wd.open();
createDbEnv();
}
};
//*-- action to start a crawl
public String iconStart = Constants.MUSTRU_HOME + File.separator + "icons" + File.separator + "crawl-start.png";
private String logFile = Constants.MUSTRU_HOME + File.separator + "bin" + File.separator + "scripts" + File.separator + "logs" + File.separator + "mustru.log";
public Action actionStart = new Action( "&Start Crawl", ImageDescriptor.createFromFile(null, iconStart))
{ public void run()
{ RunIndex ri = new RunIndex(args);
ProgressMonitorDialog pmd = new ProgressMonitorDialog( getShell() );
try { pmd.run(true, true, ri); }
catch (InvocationTargetException ie) { System.out.println("IE " + ie.getMessage()); }
catch (InterruptedException ie) { System.out.println("AE " + ie.getMessage()); }
dumpIndex(logFile, ri.isJobRan());
}
};
//*-- action to repair the index
public String iconRepair = Constants.MUSTRU_HOME + File.separator + "icons" + File.separator + "index-repair.png";
public String repairFile = Constants.MUSTRU_HOME + File.separator + "tmp" + File.separator + "repair.txt";
public Action actionRepair = new Action( "&Repair Index", ImageDescriptor.createFromFile(null, iconRepair))
{ public void run()
{ RunRepair rr = new RunRepair();
ProgressMonitorDialog pmd = new ProgressMonitorDialog( getShell() );
try { pmd.run(true, true, rr); }
catch (InvocationTargetException ie) { System.out.println("IE " + ie.getMessage()); }
catch (InterruptedException ie) { System.out.println("AE " + ie.getMessage()); }
dumpRepair(repairFile, rr.isJobRan());
}
};
//*-- Exit
public String iconExit = Constants.MUSTRU_HOME + File.separator + "icons" + File.separator + "exit.png";
public Action actionExit = new Action("&Exit", ImageDescriptor.createFromFile(null, iconExit))
{ public void run()
{ Constants.getDbt().closeEnv(); getShell().dispose(); }
};
//*-- action to summarize the index
public String iconSummarize = Constants.MUSTRU_HOME + File.separator + "icons" + File.separator + "index-summary.png";
public String summaryFile = Constants.MUSTRU_HOME + File.separator + "tmp" + File.separator + "summary.txt";
Action actionSummary = new Action( "&Summarize Index", ImageDescriptor.createFromFile(null, iconSummarize))
{ public void run()
{ RunSummary rs = new RunSummary();
ProgressMonitorDialog pmd = new ProgressMonitorDialog( getShell() );
try { pmd.run(true, true, rs); }
catch (InvocationTargetException ie) { System.out.println("IE " + ie.getMessage()); }
catch (InterruptedException ie) { System.out.println("AE " + ie.getMessage()); }
dumpSummary(summaryFile, rs.isJobRan());
}
};
//*-- action to search the index
public String iconSearch = Constants.MUSTRU_HOME + File.separator + "icons" + File.separator + "search.png";
public Action actionSearch = new Action( "&Search", ImageDescriptor.createFromFile(null, iconSearch))
{ public void run()
{ InputDialog dialog = new InputDialog(getShell(), "Search Engine Query", "Please enter the query below:", getQuery(), iv);
if (dialog.open() == Window.OK)
{SearchQuery ti = new SearchQuery();
ti.dumpHits(ti.getHits(dialog.getValue()), false);
dumpResults(ti.getResults());
setQuery(dialog.getValue());
}
}
};
//*-- action to load the Q&A system
public String iconLoadQA = Constants.MUSTRU_HOME + File.separator + "icons" + File.separator + "qa-load.png";
public Action actionLoad = new Action( "&Load QA Module", ImageDescriptor.createFromFile(null, iconLoadQA))
{ public void run()
{ //*-- check if Q&A system was loaded earlier
if (rq != null)
{ String[] results = {"QA System is already loaded."}; dumpResults(results); return; }
rq = new RunQAStartup();
ProgressMonitorDialog pmd = new ProgressMonitorDialog( getShell() );
try { pmd.run(true, true, rq); }
catch (InvocationTargetException ie) { System.out.println("IE " + ie.getMessage()); }
catch (InterruptedException ie) { System.out.println("AE " + ie.getMessage()); }
String[] results = {"QA Module "};
results[0] += (rq.isJobRan()) ? " initialized successfully.": " was NOT initialized.";
dumpResults(results);
}
};
//*-- action to ask questions
public String iconQuestion = Constants.MUSTRU_HOME + File.separator + "icons" + File.separator + "question.png";
public Action actionQuestion = new Action( "&Ask", ImageDescriptor.createFromFile(null, iconQuestion))
{ public void run()
{
//*-- first, check if the QA system was loaded
if (rq == null) actionLoad.run();
//*-- next, fetch the question and submit to the search engine
InputDialog dialog = new InputDialog(getShell(), "Ask a Question", "Please enter the question below:", getQuestion(), iv);
if (dialog.open() == Window.OK)
{ SearchQuestion tq = rq.getSq();
tq.dumpHits(tq.getHits(dialog.getValue()), false); //*-- true to explain the results
dumpResults(tq.getResults());
setQuestion(dialog.getValue());
}
}
};
//*-- action to get help
public String iconHelp = Constants.MUSTRU_HOME + File.separator + "icons" + File.separator + "start-here.png";
public Action actionAbout = new Action( "&About Mustru", ImageDescriptor.createFromFile(null, iconHelp))
{ public void run() { MessageDialog.openInformation(getShell(), "Message", "Mustru is a Question and Answer system / search engine to find " +
" useful information on your desktop. Check the docs folder under the installation directory for more documentation."); }
};
//*-- constructor to create the menus
public OnlineIndex(Shell parentShell)
{ super(parentShell); addMenuBar(); addToolBar(SWT.FLAT);
args = new String[2];
//*-- set the index and database directories
CrawlConfig crawlConfig = new CrawlConfig(false); //*-- initialize from the properties file
Constants.setDBDIR( crawlConfig.getDbDir() ); Constants.setINDEXDIR( crawlConfig.getIndexDir() );
Constants.setWEBDIR(crawlConfig.getWebDir());
createDbEnv();
//addStatusLine();
}
//*-- create the database environment
private void createDbEnv()
{
//*-- create the database environment in the Constants
if (Constants.getDbt() != null) Constants.getDbt().closeEnv();
DbTools dbt = new DbTools();
if (Constants.getDBDIR().length() > 0) dbt.openEnv(Constants.getDBDIR(), false);
Constants.setDbt(dbt);
}
//*-- Add the tool bar.
protected ToolBarManager createToolBarManager(int style)
{
ToolBarManager toolBarManager = new ToolBarManager(style);
addAction(toolBarManager, actionNew, true);
addAction(toolBarManager, actionEdit, true);
addAction(toolBarManager, actionSearch, true);
addAction(toolBarManager, actionQuestion, true);
toolBarManager.add(new Separator());
addAction(toolBarManager, actionExit, true);
toolBarManager.update(true);
actionNew.setToolTipText("New Crawl");
actionEdit.setToolTipText("Edit Crawl");
actionExit.setToolTipText("Exit");
actionSearch.setToolTipText("Search");
actionQuestion.setToolTipText("Ask a Question");
return (toolBarManager);
}
//*-- add the name of the action in the toolbar
public void addAction(ToolBarManager manager, Action action, boolean displayText)
{ if (!displayText) manager.add(action);
else
{ ActionContributionItem item = new ActionContributionItem(action);
item.setMode(ActionContributionItem.MODE_FORCE_TEXT);
manager.add(item);
}
}
//*-- initialize the text window
protected Control createContents(Composite parent)
{
//*-- brand the window with the title and icon
getShell().setText("Mustru Question & Answer v0.1");
getShell().setImage(new Image(parent.getDisplay(), Constants.MUSTRU_HOME + File.separator + "icons" + File.separator + "mustru_16.png"));
//*-- assign the colors
backYellow = new Color(parent.getDisplay(), 231, 231, 191);
backWhite = new Color(parent.getDisplay(), 218, 218, 237);
frontBlue = new Color(parent.getDisplay(), 0, 22, 135);
frontRed = new Color(parent.getDisplay(), 255, 0, 0);
//*-- create the table and columns
table = new Table ( getShell(), SWT.BORDER | SWT.FULL_SELECTION );
table.setLinesVisible(true); table.setHeaderVisible(true);
table.setLayout(new GridLayout() );
tcol1 = new TableColumn( table, SWT.LEFT, 0);
tcol2 = new TableColumn( table, SWT.LEFT, 1);
return(table);
}
//*-- build the menu manager with the four main menus
protected MenuManager createMenuManager()
{
MenuManager barMenuManager = new MenuManager();
MenuManager crawlMenu = new MenuManager("&Crawl");
MenuManager indexMenu = new MenuManager("&Index");
MenuManager testMenu = new MenuManager("&Test");
MenuManager helpMenu = new MenuManager("&Help");
barMenuManager.add(crawlMenu);
barMenuManager.add(indexMenu);
barMenuManager.add(testMenu);
barMenuManager.add(helpMenu);
crawlMenu.add(actionNew);
crawlMenu.add(actionEdit);
crawlMenu.add(actionStart);
crawlMenu.add(new Separator());
crawlMenu.add(actionExit);
indexMenu.add(actionRepair);
indexMenu.add(actionSummary);
testMenu.add(actionSearch);
testMenu.add(actionLoad);
testMenu.add(actionQuestion);
helpMenu.add(actionAbout);
barMenuManager.updateAll(true);
return barMenuManager;
}
/**
* MAIN: Start the application viewer with an initial splash screen
*/
public static void main(final String[] args)
{
//*-- generate the splash screen
final Display display = new Display();
final int[] numProgIncr = {3};
//final Image image = new Image(display, 300, 300);
final Image image = new Image(display, Constants.MUSTRU_HOME + File.separator + "icons" + File.separator + "mustruSplash.png");
final Shell splash = new Shell(SWT.ON_TOP);
final ProgressBar bar = new ProgressBar(splash, SWT.NONE);
bar.setMaximum(numProgIncr[0]);
Label label = new Label(splash, SWT.NONE);
label.setImage(image);
FormLayout layout = new FormLayout();
splash.setLayout(layout);
FormData labelData = new FormData();
labelData.right = new FormAttachment(100, 0);
labelData.bottom = new FormAttachment(100, 0);
label.setLayoutData(labelData);
FormData progressData = new FormData();
progressData.left = new FormAttachment(0, 5);
progressData.right = new FormAttachment(100, -5);
progressData.bottom = new FormAttachment(100, -5);
bar.setLayoutData(progressData);
splash.pack();
Rectangle splashRect = splash.getBounds();
Rectangle displayRect = display.getBounds();
int x = (displayRect.width - splashRect.width) / 2;
int y = (displayRect.height - splashRect.height) / 2;
splash.setLocation(x, y);
splash.open();
//*-- start the Online Index application
display.asyncExec(
new Runnable()
{
public void run()
{
int i = 0;
PropertyConfigurator.configure (Constants.LOG4J_FILE); bar.setSelection(i + 1); numProgIncr[0]--;
OnlineIndex oi = new OnlineIndex(null); oi.copyArgs(args); bar.setSelection(i + 1); numProgIncr[0]--;
ApplicationWindow viewer = oi; bar.setSelection(i + 1); numProgIncr[0]--;
splash.close(); image.dispose();
viewer.setBlockOnOpen(true);
viewer.open();
}
}
); //*-- end of display asynexec
//*-- wait till the app starts
while (numProgIncr[0] != 0)
if (!display.readAndDispatch()) display.sleep();
display.dispose();
}
/**
* Save any passed command line arguments in instance vars
* @param args
*/
public void copyArgs(String[] args)
{ if (this.args.length < args.length) this.args = new String[args.length];
for (int i = 0; i < args.length; i++) this.args[i] = args[i];
}
/**
* Dump the contents of the repair file to the table
* @param filename Name of the file to dump the repair info
* @param success boolean for a status line
*/
public void dumpRepair(String filename, boolean success)
{
File file = new File(filename);
if (!file.exists()) return;
BufferedReader br = null;
table.clearAll(); table.removeAll();
tcol1.setText("RESULTS:"); tcol1.setWidth(800);
tcol2.setWidth(0);
TableItem ti = null;
try
{
String lastLine = (success) ? "INFO: The repair operation completed normally":
"WARNING: The repair operation was aborted";
ti = new TableItem(table, SWT.LEFT); ti.setBackground(backWhite);
ti.setText(lastLine);
String theLine = null;
FileInputStream fis = new FileInputStream(file);
br = new BufferedReader(new InputStreamReader(fis)); int i = 0;
while( (theLine = br.readLine() ) != null)
{ ti = new TableItem(table, SWT.LEFT, i);
ti.setBackground(backYellow); ti.setForeground(frontBlue);
ti.setText(theLine); i++;
} //*-- end of while
}
catch (FileNotFoundException e)
{ ti = new TableItem(table, SWT.LEFT, 0); ti.setBackground(backWhite); ti.setForeground(frontRed);
ti.setText("The repair file" + filename + " was not found."); }
catch (IOException e)
{ ti = new TableItem(table, SWT.LEFT, 0); ti.setBackground(backWhite); ti.setForeground(frontRed);
ti.setText("IO Error on repair file" + filename + "."); }
finally
{ try { if (br != null) br.close(); }
catch (IOException ie) { System.out.println("Could not close reader"); }
}
}
/**
* Dump the index log file to the table
* @param filename Name of the file that will contain status of the index operation
* @param success Flag for a status line
*/
public void dumpIndex(String filename, boolean success)
{
File file = new File(filename);
if (!file.exists()) return;
BufferedReader br = null;
//*-- create the first table column
table.removeAll(); table.clearAll();
tcol1.setText("Log Entries:"); tcol1.setWidth(800);
TableItem ti = null;
LinkedList<String> logList = new LinkedList<String>(); int MAX_ENTRIES = 21;
try
{
//*-- dump a message if the task was cancelled
String lastLine = (success) ? "INFO: The index operation completed normally":
"WARNING: The index operation was aborted";
ti = new TableItem(table, SWT.LEFT); ti.setBackground(backWhite);
ti.setText(lastLine);
//*-- read the file in reverse and save the last 10 entries
String theLine = "";
FileInputStream fis = new FileInputStream(file);
br = new BufferedReader(new InputStreamReader(fis)); int numItems = 0;
while( (theLine = br.readLine() ) != null)
{ if (++numItems < MAX_ENTRIES) logList.add(theLine);
else { logList.removeFirst(); logList.addLast(theLine); }
} //*-- end of while
//*-- dump the latest log entries to the table
for (int i = 0; i < logList.size(); i++)
{ ti = new TableItem(table, SWT.LEFT, i);
ti.setBackground(backYellow); ti.setForeground(frontBlue);
ti.setText( (String) logList.get(i));
}
}
catch (FileNotFoundException e)
{ ti = new TableItem(table, SWT.LEFT, 0); ti.setBackground(backWhite); ti.setForeground(frontRed);
ti.setText("The log file" + filename + " was not found."); }
catch (IOException e)
{ ti = new TableItem(table, SWT.LEFT, 0); ti.setBackground(backWhite); ti.setForeground(frontRed);
ti.setText("IO Error on log file" + filename + "."); }
finally
{ try { if (br != null) br.close(); }
catch (IOException ie) { System.out.println("Could not close reader"); }
}
}
/**
* Dump the contents of the summary file to the table
* @param filename Name of the file containing the summary info
* @param success boolean Flag indicating the status line
*/
public void dumpSummary(String filename, boolean success)
{
File file = new File(filename);
if (!file.exists()) return;
BufferedReader br = null;
//*-- create the first table column
table.removeAll(); table.clearAll();
tcol1.setText("File Type:"); tcol1.setWidth(300);
tcol2.setText("Number"); tcol2.setWidth(100);
TableItem ti = null;
try
{
String lastLine = (success) ? "INFO: The summary operation completed normally":
"WARNING: The summary operation was aborted";
ti = new TableItem(table, SWT.LEFT); ti.setBackground(backWhite);
ti.setText(0, lastLine);
String theLine = null;
FileInputStream fis = new FileInputStream(file);
br = new BufferedReader(new InputStreamReader(fis)); int i = 0;
while( (theLine = br.readLine() ) != null)
{
if (theLine.contains(":"))
{ ti = new TableItem(table, SWT.LEFT, i);
ti.setBackground(backYellow); ti.setForeground(frontBlue);
String[] parts = theLine.split(":");
ti.setText(0, parts[0]); ti.setText(1, parts[1]); i++;
}
} //*-- end of while
}
catch (FileNotFoundException e)
{ ti = new TableItem(table, SWT.LEFT, 0); ti.setBackground(backWhite);
ti.setText("The summary file" + filename + " was not found."); }
catch (IOException e)
{ ti = new TableItem(table, SWT.LEFT, 0); ti.setBackground(backWhite);
ti.setText("IO Error on summary file" + filename + "."); }
finally
{ try { if (br != null) br.close(); }
catch (IOException ie) { System.out.println("Could not close reader"); }
}
}
/**
* Dump the passed results to the table
* @param results
*/
public void dumpResults(String[] results)
{
//*-- create the first table column
table.removeAll(); table.clearAll();
tcol1.setText("Results:"); tcol1.setWidth(800);
tcol2.setWidth(0);
TableItem ti = null;
//*-- dump the results to the table
for (int i = 0; i < results.length; i++)
{
ti = new TableItem(table, SWT.LEFT, i);
ti.setBackground( (results[i].equals("") ) ? backWhite: backYellow);
ti.setText(results[i]);
}
//*-- special case if not results were found
if (results.length == 0)
{ ti = new TableItem(table, SWT.LEFT, 0);
ti.setBackground(backWhite);
ti.setText("No results were found ...");
}
}
public String getQuery()
{ return query; }
public void setQuery(String query)
{ this.query = query; }
public String getQuestion()
{ return question; }
public void setQuestion(String question)
{ this.question = question; }
}