/**
 * Copyright 2008-2009 DRIVER PROJECT (ICM UW)
 * Original author: Marek Horst
 *
 * Licensed 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 eu.dnetlib.data.index;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

import javax.jws.WebService;
import javax.xml.ws.wsaddressing.W3CEndpointReference;

import org.apache.log4j.Logger;
import org.springframework.util.StringUtils;

import eu.dnetlib.resultset.impl.builder.IResultSetBuilder;
import eu.dnetlib.data.index.ws.bbq.BBQueryNormalizer;
import eu.dnetlib.data.index.ws.commons.event.IndexError;
import eu.dnetlib.data.index.ws.commons.event.OptimizeIndexEvent;
import eu.dnetlib.data.index.ws.commons.event.response.GenericEventResponse;
import eu.dnetlib.data.index.ws.commons.event.response.GenericEventResponse.Status;
import eu.dnetlib.data.index.ws.dataprov.CreateBrowseBulkDataDTO;
import eu.dnetlib.data.index.ws.dataprov.CreateSearchBulkDataDTO;
import eu.dnetlib.common.ws.dataprov.DataProviderException;
import eu.dnetlib.data.index.ws.dataprov.DataProviderSearchProperties;
import eu.dnetlib.data.index.ws.dataprov.IIndexDataProvider;
import eu.dnetlib.common.ws.dataprov.ResultsResponse;
import eu.dnetlib.common.ws.nh.deleg.NotificationDelegator;
import eu.dnetlib.data.index.ws.yadda.DriverQuery;
import eu.dnetlib.data.index.ws.yadda.SearchModuleFacade;
import eu.dnetlib.enabling.is.lookup.rmi.ISLookUpDocumentNotFoundException;
import eu.dnetlib.enabling.is.lookup.rmi.ISLookUpException;
import eu.dnetlib.enabling.is.lookup.rmi.ISLookUpService;
import eu.dnetlib.enabling.resultset.rmi.ResultSetService;

import pl.edu.icm.yadda.service.search.SearchException;
import pl.edu.icm.yadda.service.search.errors.EmptyQueryException;
import pl.edu.icm.yadda.service.search.errors.NoSuchIndexException;
import pl.edu.icm.yadda.service.search.searching.SearchResults;
import pl.edu.icm.yadda.service.search.searching.stats.FieldStats;
import pl.edu.icm.yadda.service.search.searching.stats.QueryStats;
import pl.edu.icm.yadda.service.search.searching.stats.QueryStatsRequest;
import pl.edu.icm.yadda.service.search.searching.stats.ValueStats;
import pl.edu.icm.yadda.service.search.searching.stats.impl.QueryStatsImpl;

/**
 * Driver Index Service Facade.
 * @author mhorst
 *
 */
@WebService(endpointInterface="eu.dnetlib.data.index.IIndexService",
		targetNamespace = "http://schemas.xmlsoap.org/soap/envelope/")
public class IndexServiceFacade implements IIndexService {
	
	protected static final Logger log = Logger.getLogger(IndexServiceFacade.class);
	
	public static final String QUERY_DELIMITER = "&";
	public static final String INDEX_DELIMITER = ",";
	public static final String QUERY_PREFIX = "query=";
	
	public static final String GROUP_BY_PREFIX = "groupby";
	public static final String GROUP_BY_DELIMITER = ",";
	
	public static final String ITERATE_ALL_SUPPORTED_PARAM_KEY = "iterateAll";
	
	/**
	 * Current index service version.
	 */
	private String indexVersion;
	
	/**
	 * Index data provider module.
	 */
	private IIndexDataProvider indexDataProvider;
	
	/**
	 * Yadda search module facade.
	 */
	private SearchModuleFacade searchModuleFacade;
	
	/**
	 * IS-LU service.
	 */
	private ISLookUpService lookUpService;

	/**
	 * Result Set service.
	 */
	private ResultSetService resultSetService;
	
	/**
	 * Result Set service location.
	 */
	private String resultSetLocation;
	
	/**
	 * ResultSet builder module. Provides direct access to the embedded IndexResultSet instance
	 * or builds ResultSetPortType to the remote ResultSet service.
	 */
	private IResultSetBuilder resultSetBuilder;
	
//	ResultSet properties:
	private String dataProviderServiceAddress;
	private int initialPageSize;
	private int expiryTime;
	private int keepAliveTime;
	
	/**
	 * Maximum results analyzed when getting browsing statistics.
	 */
	private int browsingStatsMaxAnalyzed;

	
	/**
	 * IndexService optimization flag.
	 */
	private boolean optimizeOnStartup;
	
	/**
	 * Notification delegator. Delegates notifications to proper notification
	 * consumer.
	 */
	private NotificationDelegator notificationDelegator;
	
	/**
	 * Big boolean queries normalizer module.
	 */
	private BBQueryNormalizer bbQueryNormalizer;
	
	/**
	 * Spring init method.
	 */
	public void init() {
		this.resultSetService = resultSetBuilder.build(resultSetLocation);
		
		if (optimizeOnStartup) {
			log.info("starting index optimization...");
			OptimizeIndexEvent optimizeEvent = new OptimizeIndexEvent();
			optimizeEvent.setOptimizeAll(true);
			GenericEventResponse eventResponse = searchModuleFacade.notify(optimizeEvent);
			if (eventResponse==null) {
				log.warn("Got null event response after index optimization!");
			} else {
				if (eventResponse.getStatus()==Status.FINISHED) {
					log.info("optimization finished.");
				} else if (eventResponse.getStatus()==Status.ERROR) {
					log.error("Some errors occured during optimization process!");
					if (eventResponse.getErrors()!=null) {
						for (IndexError currentError: eventResponse.getErrors()) {
							if (currentError.getCause()!=null)
								log.error(currentError.getMsg(), currentError.getCause());
							else
								log.error(currentError.getMsg());
						}
					}
				} else {
					log.warn("bad status after optimization process");
				}
			}
		} else {
			log.info("index optimization at service startup disabled");
		}
	}
	
	/* (non-Javadoc)
	 * @see eu.dnetlib.data.index.IIndexService#getBrowsingStatistics(java.lang.String, java.lang.String)
	 */
	public W3CEndpointReference getBrowsingStatistics(String query, String ixId,
			String mdFormatId, String layoutId) 
		throws IndexServiceException {
		if (query==null || ixId==null)
			throw new IllegalArgumentException("Neither query nor ixId can be null!");
//		parsing query
		String[] parsedQuery = StringUtils.delimitedListToStringArray(query, QUERY_DELIMITER);
		if (parsedQuery.length==0)
			throw new IllegalArgumentException("Invalid query parameter: "+query);
		String cqlQuery = parsedQuery[0];
		if (cqlQuery.toLowerCase().startsWith(QUERY_PREFIX)) 
			cqlQuery = cqlQuery.substring(QUERY_PREFIX.length(), cqlQuery.length());
		log.debug("Parsed cql query: "+ cqlQuery);
		cqlQuery = bbQueryNormalizer.parse(cqlQuery);
		log.debug("BBQ normalized cql query: "+ cqlQuery);
		if (cqlQuery.trim().length()==0)
			throw new IllegalArgumentException("Invalid query parameter: "+query
					+ " . Empty cqlQuery part is currently unsupported!");

		String[] sruClauses;
		Collection<String> statFields = new ArrayList<String>();
		if (parsedQuery.length > 1) {
			Collection<String> sruClauseList = new ArrayList<String>();
			parseBrowsingClauses(parsedQuery, sruClauseList, statFields);
			sruClauses = sruClauseList.toArray(new String[0]);
			log.debug("Parsed " + sruClauses.length + " parts of SRU.");
			log.debug("Parsed " + statFields.size() + " parts of statFields.");
		} else {
			sruClauses = new String[0];
		}
//		parsing ixId
		ixId = ixId.replace(" ", "").replace("\t", "").replace("\n", "");
		String[] indexIds = StringUtils.delimitedListToStringArray(ixId, INDEX_DELIMITER);
		if (indexIds.length==0)
			throw new IllegalArgumentException("Invalid ixId parameter: "+ixId);
		if (indexIds.length==1 && 
				indexIds[0].toUpperCase().equals(DataProviderSearchProperties.INDEX_IDS_ALL))
			indexIds[0] = DataProviderSearchProperties.INDEX_IDS_ALL;

		DriverQuery driverQuery = new DriverQuery();
		driverQuery.setCqlQuery(cqlQuery);
		driverQuery.setSruClauses(sruClauses);
		driverQuery.setStartPosition(0);
		driverQuery.setSize(initialPageSize);
		driverQuery.setMdFormatId(mdFormatId);
		driverQuery.setLayoutId(layoutId);
		
		QueryStatsRequest queryStatsRequest = new QueryStatsRequest(statFields);
		queryStatsRequest.setMaxAnalyzed(browsingStatsMaxAnalyzed);
		log.debug("browsingStatsMaxAnalyzed: "+browsingStatsMaxAnalyzed);
		if (statFields!=null && statFields.size()>0) {
			Iterator<String> it = statFields.iterator();
			while(it.hasNext())
				log.debug("statFields: "+it.next());
		} else
			log.debug("statFields: no stat fields");
		
		QueryStats queryStats = null;
		String bdId = null;
		try {
			try {
				if (indexIds.length==1 &&
						indexIds[0].equals(DataProviderSearchProperties.INDEX_IDS_ALL)) {
					log.debug("getQueryStats() performed for all indexes");
					queryStats = searchModuleFacade.getQueryStats(queryStatsRequest, driverQuery, null);
				} else
					queryStats = searchModuleFacade.getQueryStats(queryStatsRequest, driverQuery, indexIds);
				if (queryStats==null)
					throw new IndexServiceException("Got null browse results from YIS! " +
						"query: "+query+", indexId: "+ixId);
			} catch (EmptyQueryException eqExc) {
				log.warn("Assuming 0 results when empty browse query", eqExc);
				queryStats = new QueryStatsImpl(null);
			} catch (NoSuchIndexException nsiEx) {
				log.warn("Assuming 0 results when no index existing", nsiEx);
				queryStats = new QueryStatsImpl(null);
				throw (IndexServiceException) 
					new IndexServiceException("No such index.").initCause(nsiEx);
			}
//			TODO remove this debugging part!
			log.debug("queryStats.getAnalyzedNumber: "+queryStats.getAnalyzedNumber());
			log.debug("queryStats.getResultsNumber: "+queryStats.getResultsNumber());
			if (queryStats.getFieldStats()!=null) {
				Iterator<? extends FieldStats> it = queryStats.getFieldStats().iterator();
				while(it.hasNext()) {
					FieldStats currentFieldStats = it.next();
					log.debug("Field name: "+currentFieldStats.getFieldName());
					if (currentFieldStats.getStats()!=null) {
						Iterator<? extends ValueStats> itStats = currentFieldStats.getStats().iterator();
						while (itStats.hasNext()) {
							ValueStats currentStats = itStats.next();
							log.debug("currentStats value: "+currentStats.getValue());
							log.debug("currentStats occurences: "+currentStats.getOccurences());
						}
					}
				}
			}
			
			CreateBrowseBulkDataDTO bulkDataDTO = new CreateBrowseBulkDataDTO(queryStats);
			bdId = indexDataProvider.createBulkData(bulkDataDTO);
//			setting total number of results to avoid calling getNumberOfResults
			//CreatePullRSType pullRSType = null;
			//pullRSType = new CreatePullRSType();
			//pullRSType.setTotal(bulkDataDTO.getSize());
//			keepAliveTime support
			//pullRSType.setKeepAliveTime(keepAliveTime);
			W3CEndpointReference epr = resultSetService.createPullRS(dataProviderServiceAddress, 
					bdId, initialPageSize, expiryTime, "", keepAliveTime, bulkDataDTO.getSize());
			
			if (epr == null) {
				String errorContent = "Exception occured when creating pull result set for bdId " + bdId;
				log.error(errorContent);
				throw new IndexServiceException (errorContent + 
					"; nested error message: ");//+e.getMessage(), e);
			}
			
			return epr;
			
		} catch (DataProviderException e) {
			String errorContent = "Exception occured when creating bulk data!";
			log.error(errorContent, e);
			throw new IndexServiceException(errorContent + 
					"; nested error message: "+e.getMessage(), e);
		} catch (SearchException e) {
			String errorContent = "Exception occured when performing browsing for query: "+ query + 
				", and indexId: "+ixId;
			log.error(errorContent, e);
			throw new IndexServiceException(errorContent + 
					"; nested error message: "+e.getMessage(), e);
		}
	}
	
	/**
	 * Parses source tokens, adds SRU clauses to sruClause and groupby fields to statFields.
	 * @param source
	 * @param sruClause
	 * @param statFields statFields are lowercased!
	 */
	public static void parseBrowsingClauses(String[] source, 
			Collection<String> sruClause, Collection<String> statFields) {
		if (source==null ||
				sruClause==null || statFields==null)
			throw new IllegalArgumentException("None of entry parameters can be null!");
		
		if (source.length<=1)
			return;
//		omitting cqlClause
		for (int i=1; i<source.length; i++) {
			if (source[i].toLowerCase().startsWith(GROUP_BY_PREFIX)) {
//				parsing statFields
				int eqIdx = source[i].indexOf('=');
				if (eqIdx==-1 || eqIdx==source[i].length()-1)
					log.warn("invalid groupby clause: "+ source[i]);
				else {
					String groupByValue = source[i].substring(eqIdx+1);
					String[] tempStatFields = StringUtils.delimitedListToStringArray(groupByValue, GROUP_BY_DELIMITER);
					if (tempStatFields!=null) {
						for (int k=0; k<tempStatFields.length; k++)
							statFields.add(tempStatFields[k].trim());
					}
				}
			} else
				sruClause.add(source[i]);
		}
	}

	/* (non-Javadoc)
	 * @see eu.dnetlib.data.index.IIndexService#getIndexStatistics(java.lang.String)
	 */
	public String getIndexStatistics(String ixId) throws IndexServiceException {
		try {
			return lookUpService.getResourceProfile(ixId);
		} catch (ISLookUpDocumentNotFoundException e1) {
			String errorContent = "Exception occured when geting" +
					" index statistics from IS. Profile identified by" +
					ixId + " not found in IS Registry.";
			log.error(errorContent);
			throw new IndexServiceException(errorContent);	
		} catch (ISLookUpException e) {
			throw new IndexServiceException(
					"Exception occured when getting index statistics from IS!" + 
					"; nested error message: "+e.getMessage(), e);
		}	
	}

	/* (non-Javadoc)
	 * @see eu.dnetlib.data.index.IIndexService#getListOfIndices()
	 */
	public String[] getListOfIndices() {
		Collection<String> result = searchModuleFacade.listIndexNames();
		if (result==null || result.size()==0) {
			return null;
		} else {
			return (String[]) result.toArray(new String[0]);//new Array1Ext(result.toArray(new String[0]));
		}
		
	}
	
	/* (non-Javadoc)
	 * @see eu.dnetlib.data.index.IIndexService#getListOfIndicesCSV()
	 */
	public String getListOfIndicesCSV() {
		Collection<String> result = searchModuleFacade.listIndexNames();
		if (result==null || result.size()==0) {
			return "";
		} else {
			return StringUtils.arrayToCommaDelimitedString(result.toArray());
		}
	}
	
	/* (non-Javadoc)
	 * @see eu.dnetlib.data.index.IIndexService#identify()
	 */
	public String identify() {
		return getIndexVersion();
	}

	/* (non-Javadoc)
	 * @see eu.dnetlib.data.index.IIndexService#indexLookup(java.lang.String, java.lang.String, java.lang.String, java.lang.String)
	 */
	public W3CEndpointReference indexLookup(String ixId, String query, 
			String mdFormatId, String layoutId) throws IndexServiceException {
		if (query==null || ixId==null)
			throw new IllegalArgumentException("Neither query nor ixId can be null!");
//		parsing query
		String[] parsedQuery = StringUtils.delimitedListToStringArray(query, QUERY_DELIMITER);
		if (parsedQuery.length==0)
			throw new IllegalArgumentException("Invalid query parameter: "+query);
		String cqlQuery = parsedQuery[0];
		if (cqlQuery.toLowerCase().startsWith(QUERY_PREFIX)) 
			cqlQuery = cqlQuery.substring(QUERY_PREFIX.length(), cqlQuery.length());
		log.debug("Parsed cql query: "+ cqlQuery);
		cqlQuery = bbQueryNormalizer.parse(cqlQuery);
		log.debug("BBQ normalized cql query: "+ cqlQuery);
		String[] sruClauses;
		boolean isIterateAll = false;
		if (parsedQuery.length > 1) {
			List<String> sruClausesWork = new ArrayList<String>(); 
			for (int i = 0; i < parsedQuery.length - 1; i++) {
				if (isIterateAllParameter(parsedQuery[i+1]))
					isIterateAll=true;
				else
					sruClausesWork.add(parsedQuery[i+1]);
			}
			sruClauses = sruClausesWork.toArray(new String[sruClausesWork.size()]);
			log.debug("Parsed " + sruClauses.length + " parts of SRU.");
		} else {
			sruClauses = new String[0];
		}
//		parsing ixId
		ixId = ixId.replace(" ", "").replace("\t", "").replace("\n", "");
		String[] indexIds = StringUtils.delimitedListToStringArray(ixId, INDEX_DELIMITER);
		if (indexIds.length==0)
			throw new IllegalArgumentException("Invalid ixId parameter: "+ixId);
		if (indexIds.length==1 && 
				indexIds[0].toUpperCase().equals(DataProviderSearchProperties.INDEX_IDS_ALL))
			indexIds[0] = DataProviderSearchProperties.INDEX_IDS_ALL;

		DriverQuery driverQuery = new DriverQuery();
		driverQuery.setIterateAll(isIterateAll);
		driverQuery.setCqlQuery(cqlQuery);
		driverQuery.setSruClauses(sruClauses);
		driverQuery.setMdFormatId(mdFormatId);
		driverQuery.setLayoutId(layoutId);
		driverQuery.setStartPosition(0);
		driverQuery.setSize(initialPageSize);
		SearchResults searchResults = null;
		String bdId = null;
		try {
			try {
				if (indexIds.length==1 &&
						indexIds[0].equals(DataProviderSearchProperties.INDEX_IDS_ALL))
					searchResults = searchModuleFacade.search(driverQuery);
				else
					searchResults = searchModuleFacade.search(driverQuery,indexIds);
				if (searchResults==null)
					throw new IndexServiceException("Got null search results from YIS! " +
						"query: "+query+", indexId: "+ixId+", mdFormatId: "+mdFormatId + 
						"layoutId: " + layoutId);
			} catch (EmptyQueryException eqExc) {
				log.warn("Assuming 0 results when empty query", eqExc);
				searchResults = new SearchResults();
				searchResults.setCount(0);
			} catch (NoSuchIndexException nsiEx) {
				log.warn("Assuming 0 results when no index existing", nsiEx);
				searchResults = new SearchResults();
				searchResults.setCount(0);
				throw (IndexServiceException) 
					new IndexServiceException("No such index.").initCause(nsiEx);
			}
			CreateSearchBulkDataDTO bulkDataDTO = new CreateSearchBulkDataDTO();
			bulkDataDTO.setIndexIds(indexIds);
			bulkDataDTO.setCqlQuery(cqlQuery);
			bulkDataDTO.setSruClauses(sruClauses);
			bulkDataDTO.setMdFormatId(mdFormatId);
			bulkDataDTO.setLayoutId(layoutId);
			bulkDataDTO.setCache(searchResults);
			bdId = indexDataProvider.createBulkData(bulkDataDTO);
//			setting total number of results to avoid calling getNumberOfResults
			//CreatePullRSType pullRSType = null;
			//pullRSType = new CreatePullRSType();
			//pullRSType.setTotal(searchResults.getCount());
//			keepAliveTime support
			//pullRSType.setKeepAliveTime(keepAliveTime);
			W3CEndpointReference epr = resultSetService.createPullRS(dataProviderServiceAddress, 
					bdId, initialPageSize, expiryTime, "", keepAliveTime, searchResults.getCount());
			
			if (epr == null) {
				String errorContent = "Exception occured when creating pull result set for bdId " + bdId;
				log.error(errorContent);
				throw new IndexServiceException(errorContent + 
					"; nested error message: ");//+e.getMessage(), e);
			}
			return epr;
		
		} catch (DataProviderException e) {
			String errorContent = "Exception occured when creating bulk data!";
			log.error(errorContent, e);
			throw new IndexServiceException(errorContent + 
					"; nested error message: "+e.getMessage(), e);
		} catch (SearchException e) {
			String errorContent = "Exception occured when performing search for query: "+ query + 
				", and indexId: "+ixId;
			log.error(errorContent, e);
			throw new IndexServiceException(errorContent + 
					"; nested error message: "+e.getMessage(), e);
		}
	}

	/**
	 * Checks if given parameter affects enabling iterateAll mode.
	 * @param param
	 * @return true if iterateAll mode should be enabled
	 */
	public static boolean isIterateAllParameter(String param) {
		if (param==null)
			return false;
		int eqPos = param.indexOf('=');
		if (eqPos>0) {
			String[] tokens = StringUtils.delimitedListToStringArray(param, "=");
			if (tokens.length==2) {
				if (tokens[0].trim().equalsIgnoreCase(ITERATE_ALL_SUPPORTED_PARAM_KEY) &&
						Boolean.parseBoolean(tokens[1].trim()))
					return true;
				else
					return false;
			} else {
				return false;
			}
			
		} else {
			return false;
		}
	}
	
	/* (non-Javadoc)
	 * @see eu.dnetlib.data.index.ws.nh.INotificationHandler#notify(java.lang.String, java.lang.String, java.lang.String, java.lang.String)
	 */
	public boolean notify(String subscrId, String topic, String isId,
			String message) {
		return notificationDelegator.notify(subscrId, topic, isId, message);
	}
	
	/* (non-Javadoc)
	 * @see eu.dnetlib.data.index.ws.dataprov.IDataProvider#getBulkData(java.lang.String, int, int)
	 */
	public List<String> getBulkData(String bkId, int fromPosition, int toPosition) 
		throws DataProviderException {
		try {
			return indexDataProvider.getBulkData(bkId, fromPosition, toPosition);
		} catch (DataProviderException e) {
			log.error("Exception occured when retrieving bulk data for bdId "+bkId, e);
			throw e;
		}
	}
	
	/* (non-Javadoc)
	 * @see eu.dnetlib.data.index.ws.dataprov.IDataProvider#getSimpleBulkData(java.lang.String, int, int)
	 */
	public String[] getSimpleBulkData(String bkId, int fromPosition, int toPosition) 
		throws DataProviderException {
		try {
			return indexDataProvider.getSimpleBulkData(bkId, fromPosition, toPosition);
		} catch (DataProviderException e) {
			log.error("Exception occured when retrieving bulk data for bdId "+bkId, e);
			throw e;
		}
	}


	/* (non-Javadoc)
	 * @see eu.dnetlib.data.index.ws.dataprov.IDataProvider#getNumberOfResults(java.lang.String)
	 */
	public ResultsResponse getNumberOfResults(String bkId) 
		throws DataProviderException {
		try {
			return indexDataProvider.getNumberOfResults(bkId);
		} catch (DataProviderException e) {
			log.error("Exception occured when retrieving number of results for bdId "+bkId, e);
			throw e;
		}
	}

	/**
	 * Returns current index version.
	 * @return current index version
	 */
	public String getIndexVersion() {
		return indexVersion;
	}

	/**
	 * Sets current index version.
	 * @param indexVersion
	 */
	public void setIndexVersion(String indexVersion) {
		this.indexVersion = indexVersion;
	}
	
	/**
	 * Returns internal search module facade.
	 * @return internal search module facade
	 */
	public SearchModuleFacade getSearchModuleFacade() {
		return searchModuleFacade;
	}

	/**
	 * Sets internal search module.
	 * @param searchModuleFacade
	 */
	public void setSearchModuleFacade(SearchModuleFacade searchModuleFacade) {
		this.searchModuleFacade = searchModuleFacade;
	}

	/**
	 * Returns index data provider.
	 * @return index data provider
	 */
	public IIndexDataProvider getIndexDataProvider() {
		return indexDataProvider;
	}

	/**
	 * Sets index data provider.
	 * @param indexDataProvider
	 */
	public void setIndexDataProvider(IIndexDataProvider indexDataProvider) {
		this.indexDataProvider = indexDataProvider;
	}

	/**
	 * Returns target Result Set service location.
	 * @return target Result Set service location
	 */
	public String getResultSetLocation() {
		return resultSetLocation;
	}

	/**
	 * Sets target Result Set service location.
	 * @param resultSetLocation
	 */
	public void setResultSetLocation(String resultSetLocation) {
		this.resultSetLocation = resultSetLocation;
	}

	/**
	 * Returns result set data provider service address.
	 * @return result set data provider service address
	 */
	public String getDataProviderServiceAddress() {
		return dataProviderServiceAddress;
	}

	/**
	 * Sets result set data provider service address.
	 * @param dataProviderServiceAddress
	 */
	public void setDataProviderServiceAddress(String dataProviderServiceAddress) {
		this.dataProviderServiceAddress = dataProviderServiceAddress;
	}

	/**
	 * Returns result set expiry time.
	 * @return result set expiry time
	 */
	public int getExpiryTime() {
		return expiryTime;
	}

	/**
	 * Sets result set expiry time.
	 * @param expiryTime
	 */
	public void setExpiryTime(int expiryTime) {
		this.expiryTime = expiryTime;
	}
	
	/**
	 * Returns keep alive time.
	 * @return keep alive time
	 */
	public int getKeepAliveTime() {
		return keepAliveTime;
	}

	/**
	 * Sets keep alive time.
	 * @param keepAliveTime
	 */
	public void setKeepAliveTime(int keepAliveTime) {
		this.keepAliveTime = keepAliveTime;
	}

	/**
	 * Returns result set initial page size.
	 * @return result set initial page size
	 */
	public int getInitialPageSize() {
		return initialPageSize;
	}

	/**
	 * Sets result set initial page size.
	 * @param initialPageSize
	 */
	public void setInitialPageSize(int initialPageSize) {
		this.initialPageSize = initialPageSize;
	}

	/**
	 * Returns maximum results analyzed when getting browsing statistics.
	 * @return maximum results analyzed when getting browsing statistics
	 */
	public int getBrowsingStatsMaxAnalyzed() {
		return browsingStatsMaxAnalyzed;
	}

	/**
	 * Sets maximum results analyzed when getting browsing statistics.
	 * @param browsingStatsMaxAnalyzed
	 */
	public void setBrowsingStatsMaxAnalyzed(int browsingStatsMaxAnalyzed) {
		this.browsingStatsMaxAnalyzed = browsingStatsMaxAnalyzed;
	}

	/**
	 * Returns IS-LU service.
	 * @return IS-LU service
	 */
	public ISLookUpService getLookUpService() {
		return lookUpService;
	}

	/**
	 * Sets IS-LU service.
	 * @param lookUpService
	 */
	public void setLookUpService(ISLookUpService lookUpService) {
		this.lookUpService = lookUpService;
	}

	/**
	 * Returns IndexService optimization flag.
	 * @return IndexService optimization flag
	 */
	public boolean isOptimizeOnStartup() {
		return optimizeOnStartup;
	}

	/**
	 * Sets IndexService optimization flag.
	 * @param optimizeOnStartup
	 */
	public void setOptimizeOnStartup(boolean optimizeOnStartup) {
		this.optimizeOnStartup = optimizeOnStartup;
	}

	/**
	 * Returns notification delegator.
	 * @return notification delegator
	 */
	public NotificationDelegator getNotificationDelegator() {
		return notificationDelegator;
	}

	/**
	 * Sets notification delegator.
	 * @param notificationDelegator
	 */
	public void setNotificationDelegator(NotificationDelegator notificationDelegator) {
		this.notificationDelegator = notificationDelegator;
	}

	/**
	 * Returns big boolean queries normalizer module.
	 * @return big boolean queries normalizer module
	 */
	public BBQueryNormalizer getBbQueryNormalizer() {
		return bbQueryNormalizer;
	}

	/**
	 * Sets big boolean queries normalizer module.
	 * @param bbQueryNormalizer
	 */
	public void setBbQueryNormalizer(BBQueryNormalizer bbQueryNormalizer) {
		this.bbQueryNormalizer = bbQueryNormalizer;
	}

	/**
	 * Returns ResultSet builder module.
	 * @return ResultSet builder module
	 */
	public IResultSetBuilder getResultSetBuilder() {
		return resultSetBuilder;
	}

	/**
	 * Sets ResultSet builder module.
	 * @param resultSetBuilder
	 */
	public void setResultSetBuilder(IResultSetBuilder resultSetBuilder) {
		this.resultSetBuilder = resultSetBuilder;
	}
	
}
