com.jaeksoft.searchlib.join.JoinItem Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of opensearchserver Show documentation
Show all versions of opensearchserver Show documentation
OpenSearchServer is a powerful, enterprise-class, search engine program. Using the web user interface, the crawlers (web, file, database, ...) and the REST/RESTFul API you will be able to integrate quickly and easily advanced full-text search capabilities in your application. OpenSearchServer runs on Windows and Linux/Unix/BSD.
The newest version!
/**
* License Agreement for OpenSearchServer
*
* Copyright (C) 2012-2014 Emmanuel Keller / Jaeksoft
*
* http://www.open-search-server.com
*
* This file is part of OpenSearchServer.
*
* OpenSearchServer is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* OpenSearchServer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenSearchServer.
* If not, see .
**/
package com.jaeksoft.searchlib.join;
import java.io.IOException;
import java.util.List;
import javax.xml.xpath.XPathExpressionException;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;
import com.jaeksoft.searchlib.Client;
import com.jaeksoft.searchlib.ClientCatalog;
import com.jaeksoft.searchlib.SearchLibException;
import com.jaeksoft.searchlib.filter.FilterAbstract;
import com.jaeksoft.searchlib.filter.FilterList;
import com.jaeksoft.searchlib.function.expression.SyntaxError;
import com.jaeksoft.searchlib.index.FieldCacheIndex;
import com.jaeksoft.searchlib.index.ReaderAbstract;
import com.jaeksoft.searchlib.request.AbstractRequest;
import com.jaeksoft.searchlib.request.AbstractSearchRequest;
import com.jaeksoft.searchlib.request.SearchFieldRequest;
import com.jaeksoft.searchlib.result.ResultSearchSingle;
import com.jaeksoft.searchlib.result.collector.DocIdInterface;
import com.jaeksoft.searchlib.result.collector.join.JoinUtils;
import com.jaeksoft.searchlib.util.StringUtils;
import com.jaeksoft.searchlib.util.Timer;
import com.jaeksoft.searchlib.util.XPathParser;
import com.jaeksoft.searchlib.util.XmlWriter;
import com.jaeksoft.searchlib.web.ServletTransaction;
public class JoinItem implements Comparable {
public interface OuterCollector {
public void collect(final int id, final String value);
}
public static enum JoinType {
INNER, OUTER;
private final String label = name().toLowerCase();
final public static JoinType find(String name) {
for (JoinType type : values())
if (type.name().equalsIgnoreCase(name))
return type;
return INNER;
}
public String getLabel() {
return label;
}
}
private String indexName;
private String queryTemplate;
private FilterList filterList;
private String queryString;
private String localField;
private String foreignField;
private int position;
private String paramPosition;
private boolean returnFields;
private boolean returnScores;
private boolean returnFacets;
private JoinType type;
private transient OuterCollector outerCollector;
private transient Client foreignClient;
private transient AbstractSearchRequest foreignSearchRequest;
public JoinItem() {
indexName = null;
queryTemplate = null;
queryString = null;
localField = null;
foreignField = null;
position = 0;
paramPosition = null;
returnFields = false;
returnScores = false;
returnFacets = false;
type = JoinType.INNER;
filterList = new FilterList();
outerCollector = null;
foreignSearchRequest = null;
foreignClient = null;
}
public JoinItem(JoinItem source) {
source.copyTo(this);
}
public void copyTo(JoinItem target) {
target.indexName = indexName;
target.queryTemplate = queryTemplate;
target.queryString = queryString;
target.localField = localField;
target.foreignField = foreignField;
target.position = position;
target.paramPosition = paramPosition;
target.returnFields = returnFields;
target.returnScores = returnScores;
target.returnFacets = returnFacets;
target.type = type;
target.filterList = new FilterList(filterList);
}
public JoinItem(XPathParser xpp, Node node) throws XPathExpressionException {
indexName = XPathParser.getAttributeString(node, ATTR_NAME_INDEXNAME);
queryTemplate = XPathParser.getAttributeString(node,
ATTR_NAME_QUERYTEMPLATE);
queryString = xpp.getNodeString(node, false);
localField = XPathParser.getAttributeString(node, ATTR_NAME_LOCALFIELD);
foreignField = XPathParser.getAttributeString(node,
ATTR_NAME_FOREIGNFIELD);
returnFields = Boolean.parseBoolean(XPathParser.getAttributeString(
node, ATTR_NAME_RETURNFIELDS));
returnScores = Boolean.parseBoolean(XPathParser.getAttributeString(
node, ATTR_NAME_RETURNSCORES));
returnFacets = Boolean.parseBoolean(XPathParser.getAttributeString(
node, ATTR_NAME_RETURNFACETS));
type = JoinType.find(XPathParser.getAttributeString(node,
ATTR_NAME_TYPE));
filterList = new FilterList();
}
public final String NODE_NAME_JOIN = "join";
public final String ATTR_NAME_INDEXNAME = "indexName";
public final String ATTR_NAME_QUERYTEMPLATE = "queryTemplate";
public final String ATTR_NAME_LOCALFIELD = "localField";
public final String ATTR_NAME_FOREIGNFIELD = "foreignField";
public final String ATTR_NAME_RETURNFIELDS = "returnFields";
public final String ATTR_NAME_RETURNSCORES = "returnScores";
public final String ATTR_NAME_RETURNFACETS = "returnFacets";
public final String ATTR_NAME_TYPE = "type";
public void writeXmlConfig(XmlWriter xmlWriter) throws SAXException {
xmlWriter.startElement(NODE_NAME_JOIN, ATTR_NAME_INDEXNAME, indexName,
ATTR_NAME_QUERYTEMPLATE, queryTemplate, ATTR_NAME_LOCALFIELD,
localField, ATTR_NAME_FOREIGNFIELD, foreignField,
ATTR_NAME_RETURNFIELDS, Boolean.toString(returnFields),
ATTR_NAME_RETURNSCORES, Boolean.toString(returnScores),
ATTR_NAME_RETURNFACETS, Boolean.toString(returnFacets),
ATTR_NAME_TYPE, type.name());
xmlWriter.textNode(queryString);
xmlWriter.endElement();
}
/**
* @return the indexName
*/
public String getIndexName() {
return indexName;
}
/**
* @param indexName
* the indexName to set
*/
public void setIndexName(String indexName) {
this.indexName = indexName;
}
/**
* @return the queryTemplate
*/
public String getQueryTemplate() {
return queryTemplate;
}
/**
* @param queryTemplate
* the queryTemplate to set
*/
public void setQueryTemplate(String queryTemplate) {
this.queryTemplate = queryTemplate;
}
/**
* @return the queryString
*/
public String getQueryString() {
return queryString;
}
/**
* @param queryString
* the queryString to set
*/
public void setQueryString(String queryString) {
this.queryString = queryString;
}
/**
* @return the localField
*/
public String getLocalField() {
return localField;
}
/**
* @param localField
* the localField to set
*/
public void setLocalField(String localField) {
this.localField = localField;
}
/**
* @return the foreignField
*/
public String getForeignField() {
return foreignField;
}
/**
* @param foreignField
* the foreignField to set
*/
public void setForeignField(String foreignField) {
this.foreignField = foreignField;
}
public void setOuterCollector(OuterCollector outerCollector) {
this.outerCollector = outerCollector;
}
@Override
public int compareTo(JoinItem o) {
int c = 0;
if ((c = indexName.compareTo(o.indexName)) != 0)
return c;
if ((c = queryTemplate.compareTo(o.queryTemplate)) != 0)
return c;
if ((c = queryString.compareTo(o.queryString)) != 0)
return c;
if ((c = localField.compareTo(o.localField)) != 0)
return c;
if ((c = foreignField.compareTo(o.foreignField)) != 0)
return c;
return 0;
}
public void setParamPosition(int position) {
this.position = position;
paramPosition = StringUtils
.fastConcat("jq", Integer.toString(position));
}
public int getPosition() {
return position;
}
public String getParamPosition() {
return paramPosition;
}
/**
* @return the returnFields
*/
public boolean isReturnFields() {
return returnFields;
}
/**
* @param returnFields
* the returnFields to set
*/
public void setReturnFields(boolean returnFields) {
this.returnFields = returnFields;
}
/**
* @return the returnScores
*/
public boolean isReturnScores() {
return returnScores;
}
/**
* @param returnScores
* the returnScores to set
*/
public void setReturnScores(boolean returnScores) {
this.returnScores = returnScores;
}
/**
* @return the returnFacets
*/
public boolean isReturnFacets() {
return returnFacets;
}
/**
* @param returnFacets
* the returnFacets to set
*/
public void setReturnFacets(boolean returnFacets) {
this.returnFacets = returnFacets;
}
/**
* @return the type
*/
public JoinType getType() {
return type;
}
/**
* @param type
* the type to set
*/
public void setType(JoinType type) {
this.type = type;
}
protected final Client getFogeignClient() throws SearchLibException {
Client foreignClient = ClientCatalog.getClient(indexName);
if (foreignClient == null)
throw new SearchLibException("No client found: " + indexName);
return foreignClient;
}
protected AbstractSearchRequest getForeignSearchRequest(
final Client foreignClient) throws SearchLibException {
AbstractRequest foreignRequest = StringUtils.isEmpty(queryTemplate) ? new SearchFieldRequest(
foreignClient) : foreignClient.getNewRequest(queryTemplate);
if (foreignRequest == null)
throw new SearchLibException("The request template was not found: "
+ queryTemplate);
if (!(foreignRequest instanceof AbstractSearchRequest))
throw new SearchLibException(
"The request template is not a Search request: "
+ queryTemplate);
return (AbstractSearchRequest) foreignRequest;
}
private final void lazyLoadForeignSearchRequest() throws SearchLibException {
if (foreignClient == null)
foreignClient = getFogeignClient();
if (foreignSearchRequest == null)
foreignSearchRequest = getForeignSearchRequest(foreignClient);
}
public DocIdInterface apply(AbstractSearchRequest searchRequest,
ReaderAbstract reader, DocIdInterface docs, int joinResultSize,
JoinResult joinResult, List joinFacets, Timer timer)
throws SearchLibException {
try {
FieldCacheIndex localStringIndex = reader
.getStringIndex(localField);
if (localStringIndex == null)
throw new SearchLibException(
"No string index found for the local field: "
+ localField);
lazyLoadForeignSearchRequest();
foreignSearchRequest.setStart(0);
foreignSearchRequest.setRows(0);
foreignSearchRequest.setUsers(searchRequest.getUsers());
foreignSearchRequest.setGroups(searchRequest.getGroups());
foreignSearchRequest.setQueryString(queryString);
for (FilterAbstract> filter : filterList)
foreignSearchRequest.getFilterList().add(filter);
String joinResultName = "join " + joinResult.joinPosition;
Timer t = new Timer(timer, joinResultName + " foreign search");
ResultSearchSingle resultSearch = (ResultSearchSingle) foreignClient
.request(foreignSearchRequest);
t.getDuration();
joinResult.setForeignResult(resultSearch);
if (foreignSearchRequest.isFacet()) {
if (returnFacets)
joinFacets.add(new JoinFacet(joinResult,
foreignSearchRequest.getFacetFieldList(),
resultSearch));
foreignSearchRequest.getFacetFieldList().clear();
}
ReaderAbstract foreignReader = resultSearch.getReader();
FieldCacheIndex foreignFieldIndex = foreignReader
.getStringIndex(foreignField);
if (foreignFieldIndex == null)
throw new SearchLibException(StringUtils.fastConcat(
"No string index found for the foreign field: ",
foreignField));
t = new Timer(timer, joinResultName + " join");
DocIdInterface joinDocs = JoinUtils.join(docs, localStringIndex,
resultSearch.getDocs(), foreignFieldIndex, joinResultSize,
joinResult.joinPosition, t, type, outerCollector,
foreignReader);
t.getDuration();
return joinDocs;
} catch (IOException e) {
throw new SearchLibException(e);
}
}
public void setFromServlet(ServletTransaction transaction, String prefix)
throws SearchLibException, SyntaxError {
String myPrefix = StringUtils.fastConcat(prefix, paramPosition);
String q = transaction.getParameterString(myPrefix);
if (q != null)
setQueryString(q);
myPrefix = StringUtils.fastConcat(myPrefix, ".");
filterList.addFromServlet(transaction, myPrefix);
lazyLoadForeignSearchRequest();
foreignSearchRequest.setFromServlet(transaction, myPrefix);
}
public void setParam(String param) {
if (param != null)
setQueryString(param);
}
}