/*
* Copyright 2010 Bizosys Technologies Limited
*
* Licensed to the Bizosys Technologies Limited (Bizosys) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The Bizosys licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.bizosys.hsearch.index;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.bizosys.hsearch.PerformanceLogger;
import com.bizosys.hsearch.common.Account;
import com.bizosys.hsearch.hbase.NVBytes;
import com.bizosys.hsearch.outpipe.BuildNlp;
import com.bizosys.hsearch.outpipe.BuildPreview;
import com.bizosys.hsearch.outpipe.CheckMetaInfo;
import com.bizosys.hsearch.outpipe.ComputeDynamicRanking;
import com.bizosys.hsearch.outpipe.ComputePreciousness;
import com.bizosys.hsearch.outpipe.ComputeStaticRanking;
import com.bizosys.hsearch.outpipe.ComputeTypeCodes;
import com.bizosys.hsearch.outpipe.DictionaryEnrichment;
import com.bizosys.hsearch.outpipe.HQueryParser;
import com.bizosys.hsearch.outpipe.QuerySequencing;
import com.bizosys.hsearch.outpipe.ScoreOnTitleMatch;
import com.bizosys.hsearch.outpipe.SequenceProcessor;
import com.bizosys.hsearch.query.HQuery;
import com.bizosys.hsearch.query.QueryContext;
import com.bizosys.hsearch.query.QueryPlanner;
import com.bizosys.hsearch.query.QueryResult;
import com.bizosys.oneline.ApplicationFault;
import com.bizosys.oneline.SystemFault;
import com.bizosys.oneline.conf.Configuration;
import com.bizosys.oneline.pipes.PipeOut;
import com.bizosys.oneline.util.StringUtils;
/**
* Performs Reads Operation on HSearch Index
* @author karan
*
*/
public class IndexReader {
private static final boolean INFO_ENABLED = IndexLog.l.isInfoEnabled();
private static final boolean DEBUG_ENABLED = IndexLog.l.isDebugEnabled();
private static final boolean PERF_ENABLED = PerformanceLogger.l.isDebugEnabled();
private static IndexReader singleton = null;
public static IndexReader getInstance() {
if ( null != singleton) return singleton;
synchronized (IndexReader.class) {
if ( null != singleton) return singleton;
singleton = new IndexReader();
}
return singleton;
}
private Map<String, PipeOut> readPipes = null;
private IndexReader() {
}
/**
* Creates standard sets of pipes
*/
private void createPipes() {
if ( null != this.readPipes) return;
this.readPipes = new HashMap<String, PipeOut>();
HQueryParser lqp = new HQueryParser();
this.readPipes.put(lqp.getName(), lqp);
DictionaryEnrichment de = new DictionaryEnrichment();
this.readPipes.put(de.getName(), de);
ComputePreciousness cp = new ComputePreciousness();
this.readPipes.put(cp.getName(), cp);
ComputeTypeCodes ctc = new ComputeTypeCodes();
this.readPipes.put(ctc.getName(), ctc);
QuerySequencing qs = new QuerySequencing();
this.readPipes.put(qs.getName(), qs);
SequenceProcessor sp = new SequenceProcessor();
this.readPipes.put(sp.getName(), sp);
ComputeStaticRanking csr = new ComputeStaticRanking();
this.readPipes.put(csr.getName(), csr);
CheckMetaInfo cmi = new CheckMetaInfo();
this.readPipes.put(cmi.getName(), cmi);
ComputeDynamicRanking cdr = new ComputeDynamicRanking();
this.readPipes.put(cdr.getName(), cdr);
BuildPreview bt = new BuildPreview();
this.readPipes.put(bt.getName(), bt);
ScoreOnTitleMatch stm = new ScoreOnTitleMatch();
this.readPipes.put(stm.getName(), stm);
BuildNlp nlp = new BuildNlp();
this.readPipes.put(nlp.getName(), nlp);
}
public void init(Configuration conf) throws SystemFault, ApplicationFault{
if ( null == readPipes) createPipes();
for (PipeOut pipe: readPipes.values()) {
pipe.init(conf);
}
}
/**
* Comma separates Steps
* @param stepNames
* @return Output pipes
* @throws ApplicationFault
*/
public List<PipeOut> getPipes(String stepNames) throws SystemFault {
if ( IndexLog.l.isDebugEnabled() )
IndexLog.l.debug("IndexReader: getPipes = " + stepNames);
if ( null == this.readPipes) createPipes();
String[] steps = StringUtils.getStrings(stepNames, ",");
List<PipeOut> anvils = new ArrayList<PipeOut>(steps.length);
for (String step : steps) {
PipeOut aPipe = readPipes.get(step).getInstance();
if ( null == aPipe) {
IndexLog.l.error("IndexReader: getPipes Pipe not found = " + step);
throw new SystemFault("Pipe Not Found: " + step);
}
anvils.add(aPipe);
}
return anvils;
}
public List<PipeOut> getStandardPipes() throws SystemFault {
if ( null == this.readPipes) createPipes();
return getPipes(
"HQueryParser,DictionaryEnrichment,ComputePreciousness,"+
"ComputeTypeCodes,QuerySequencing,SequenceProcessor," +
"ComputeStaticRanking,CheckMetaInfo,ComputeDynamicRanking," +
"BuildTeaser,ScoreOnTitleMatch,BuildNlp");
}
/**
* Get the document detail based on supplied document ID.
* @param origId the Original document Id
* @return Document Object
* @throws ApplicationFault
* @throws SystemFault
*/
public Doc get(String tenant, String docId) throws ApplicationFault, SystemFault{
return new Doc(tenant, docId);
}
/**
* Read the index and allows the processing to go through steps
* @param ctx User Input Query Context
* @return Query Result
* @throws ApplicationFault
* @throws SystemFault
*/
public QueryResult search(QueryContext ctx) throws ApplicationFault, SystemFault{
return search(ctx, getStandardPipes());
}
public QueryResult search(QueryContext ctx, List<PipeOut> pipes)
throws ApplicationFault, SystemFault{
if ( null == ctx) return null;
if ( INFO_ENABLED) IndexLog.l.info("IndexReader> Searching : " + ctx.queryString);
QueryPlanner planner = new QueryPlanner();
HQuery query = new HQuery(ctx, planner);
long start=0,end;
StringBuilder log = null;
if ( PERF_ENABLED) {
log = new StringBuilder();
start=System.currentTimeMillis();
}
for (PipeOut outPipe : pipes) {
if ( DEBUG_ENABLED ) {
IndexLog.l.debug(outPipe.getName() + "> Enter");
}
outPipe.visit(query, false);
if ( PERF_ENABLED) {
end = System.currentTimeMillis();
log.append(outPipe.getName()).append('=').append(end - start).append('|');
start = end;
}
if ( DEBUG_ENABLED ) {
IndexLog.l.debug(outPipe.getName() + "> Exit");
}
}
if ( PERF_ENABLED) PerformanceLogger.l.debug(log.toString());
planner.cleanup();
return query.result;
}
public static List<InvertedIndex> getInvertedIndex(long bucketId) throws ApplicationFault, SystemFault{
List<NVBytes> nvs = Account.get(bucketId);
if ( null == nvs) return null;
List<InvertedIndex> iiL = new ArrayList<InvertedIndex>(nvs.size());
for (NVBytes nv : nvs) {
if ( null == nv.data) continue;
List<InvertedIndex> indexes = InvertedIndex.read(nv.data);
if ( null == indexes) continue;
iiL.addAll(indexes);
}
return iiL;
}
}