package com.senseidb.clue;
import java.io.IOException;
import java.util.Collection;
import java.util.LinkedList;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import jline.console.ConsoleReader;
import jline.console.completer.ArgumentCompleter;
import jline.console.completer.Completer;
import jline.console.completer.FileNameCompleter;
import jline.console.completer.StringsCompleter;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.index.FieldInfo;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.LeafReader;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.store.Directory;
import com.senseidb.clue.api.BytesRefDisplay;
import com.senseidb.clue.api.IndexReaderFactory;
import com.senseidb.clue.api.QueryBuilder;
import com.senseidb.clue.commands.ClueCommand;
import com.senseidb.clue.commands.DeleteCommand;
import com.senseidb.clue.commands.DeleteUserCommitData;
import com.senseidb.clue.commands.DirectoryCommand;
import com.senseidb.clue.commands.DocSetInfoCommand;
import com.senseidb.clue.commands.DocValCommand;
import com.senseidb.clue.commands.DumpDocCommand;
import com.senseidb.clue.commands.ExitCommand;
import com.senseidb.clue.commands.ExplainCommand;
import com.senseidb.clue.commands.ExportCommand;
import com.senseidb.clue.commands.GetUserCommitDataCommand;
import com.senseidb.clue.commands.HelpCommand;
import com.senseidb.clue.commands.IndexTrimCommand;
import com.senseidb.clue.commands.InfoCommand;
import com.senseidb.clue.commands.MergeCommand;
import com.senseidb.clue.commands.NormsCommand;
import com.senseidb.clue.commands.PostingsCommand;
import com.senseidb.clue.commands.ReadonlyCommand;
import com.senseidb.clue.commands.ReconstructCommand;
import com.senseidb.clue.commands.SaveUserCommitData;
import com.senseidb.clue.commands.SearchCommand;
import com.senseidb.clue.commands.StoredFieldCommand;
import com.senseidb.clue.commands.TermVectorCommand;
import com.senseidb.clue.commands.TermsCommand;
public class ClueContext {
private final ConsoleReader consoleReader;
private final IndexReaderFactory readerFactory;
private final SortedMap<String, ClueCommand> cmdMap;
private final boolean interactiveMode;
private IndexWriter writer;
private final Directory directory;
private boolean readOnlyMode;
private final IndexWriterConfig writerConfig;
private final QueryBuilder queryBuilder;
private final Analyzer analyzerQuery;
private final BytesRefDisplay termBytesRefDisplay;
private final BytesRefDisplay payloadBytesRefDisplay;
public ClueContext(Directory dir, ClueConfiguration config, boolean interactiveMode)
throws Exception {
this.directory = dir;
this.analyzerQuery = config.getAnalyzerQuery();
this.readerFactory = config.getIndexReaderFactory();
this.readerFactory.initialize(directory);
this.queryBuilder = config.getQueryBuilder();
this.queryBuilder.initialize("contents", analyzerQuery);
this.writerConfig = new IndexWriterConfig(new StandardAnalyzer());
this.termBytesRefDisplay = config.getTermBytesRefDisplay();
this.payloadBytesRefDisplay = config.getPayloadBytesRefDisplay();
this.writer = null;
this.interactiveMode = interactiveMode;
this.cmdMap = new TreeMap<String, ClueCommand>();
// default to readonly
this.readOnlyMode = true;
// registers all the commands we currently support
new HelpCommand(this);
new ExitCommand(this);
new InfoCommand(this);
new DocValCommand(this);
new SearchCommand(this);
new TermsCommand(this);
new PostingsCommand(this);
new DocSetInfoCommand(this);
new MergeCommand(this);
new DeleteCommand(this);
new ReadonlyCommand(this);
new DirectoryCommand(this);
new ExplainCommand(this);
new NormsCommand(this);
new TermVectorCommand(this);
new StoredFieldCommand(this);
new ReconstructCommand(this);
new ExportCommand(this);
new IndexTrimCommand(this);
new GetUserCommitDataCommand(this);
new SaveUserCommitData(this);
new DeleteUserCommitData(this);
new DumpDocCommand(this);
this.consoleReader = new ConsoleReader();
this.consoleReader.setBellEnabled(false);
initAutoCompletion();
}
void initAutoCompletion() {
LinkedList<Completer> completors = new LinkedList<Completer>();
completors.add(new StringsCompleter(cmdMap.keySet()));
completors.add(new StringsCompleter(fieldNames()));
completors.add(new FileNameCompleter());
consoleReader.addCompleter(new ArgumentCompleter(completors));
}
Collection<String> fieldNames() {
LinkedList<String> fieldNames = new LinkedList<String>();
for (LeafReaderContext context : getIndexReader().leaves()) {
LeafReader reader = context.reader();
for(FieldInfo info : reader.getFieldInfos()) {
fieldNames.add(info.name);
}
}
return fieldNames;
}
public String readCommand() {
try {
return consoleReader.readLine("> ");
} catch (IOException e) {
System.err.println("Error! Clue is unable to read line from stdin: " + e.getMessage());
throw new IllegalStateException("Unable to read command line!", e);
}
}
public QueryBuilder getQueryBuilder() {
return queryBuilder;
}
public Analyzer getAnalyzerQuery() {
return analyzerQuery;
}
public BytesRefDisplay getTermBytesRefDisplay() {
return termBytesRefDisplay;
}
public BytesRefDisplay getPayloadBytesRefDisplay() {
return payloadBytesRefDisplay;
}
public void registerCommand(ClueCommand cmd){
String cmdName = cmd.getName();
if (cmdMap.containsKey(cmdName)){
throw new IllegalArgumentException(cmdName+" exists!");
}
cmdMap.put(cmdName, cmd);
}
public boolean isInteractiveMode(){
return interactiveMode;
}
public boolean isReadOnlyMode() {
return readOnlyMode;
}
public ClueCommand getCommand(String cmd){
return cmdMap.get(cmd);
}
public Map<String, ClueCommand> getCommandMap(){
return cmdMap;
}
public IndexReader getIndexReader(){
return readerFactory.getIndexReader();
}
public IndexWriter getIndexWriter(){
if (readOnlyMode) return null;
if (writer == null) {
try {
writer = new IndexWriter(directory, writerConfig);
} catch (IOException e) {
e.printStackTrace();
}
}
return writer;
}
public Directory getDirectory() {
return directory;
}
public void setReadOnlyMode(boolean readOnlyMode) {
this.readOnlyMode = readOnlyMode;
if (writer != null) {
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
writer = null;
}
}
public void refreshReader() throws Exception {
readerFactory.refreshReader();
}
public void shutdown() throws Exception{
try {
readerFactory.shutdown();
}
finally{
if (writer != null) {
writer.close();
}
}
}
}