org.sindice.siren.solr.qparser.tuple.TupleQParser Maven / Gradle / Ivy
The newest version!
/**
* Copyright (c) 2009-2011 Sindice Limited. All Rights Reserved.
*
* Project and contact information: http://www.siren.sindice.com/
*
* This file is part of the SIREn project.
*
* SIREn is a free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* SIREn 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public
* License along with SIREn. If not, see .
*/
/**
* @project siren-solr
* @author Renaud Delbru [ 25 Jul 2010 ]
* @link http://renaud.delbru.fr/
* @copyright Copyright (C) 2010 by Renaud Delbru, All rights reserved.
*/
package org.sindice.siren.solr.qparser.tuple;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.queryParser.QueryParser.Operator;
import org.apache.lucene.queryParser.standard.config.DefaultOperatorAttribute;
import org.apache.lucene.search.Query;
import org.apache.lucene.util.Version;
import org.apache.solr.analysis.BaseTokenizerFactory;
import org.apache.solr.analysis.TokenFilterFactory;
import org.apache.solr.analysis.TokenizerChain;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.params.DefaultSolrParams;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.schema.FieldType;
import org.apache.solr.search.QParser;
import org.sindice.siren.solr.analysis.NTripleQueryTokenizerFactory;
import org.sindice.siren.solr.schema.Datatype;
import org.sindice.siren.solr.schema.SirenField;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The {@link TupleQParser} is in charge of executing a Tuple query request.
*/
public abstract class TupleQParser extends QParser {
/**
* Field boosts
*/
Map boosts;
/**
* Flag for scattered multi-field match
*/
protected boolean scattered = false;
/**
* The default query operator
*/
private Operator defaultOp = Operator.AND;
private static final Logger logger = LoggerFactory.getLogger(TupleQParser.class);
public TupleQParser(final Map boosts, final String qstr,
final SolrParams localParams, final SolrParams params,
final SolrQueryRequest req) {
super(qstr, localParams, params, req);
this.boosts = boosts;
final SolrParams solrParams = localParams == null ? params : new DefaultSolrParams(localParams, params);
this.checkFieldTypes();
this.initTupleQueryFieldOperator(solrParams);
// try to get default operator from schema
defaultOp = this.getReq().getSchema().getSolrQueryParser(null).getDefaultOperator();
}
/**
* Check if all fields are of type {@link SirenField}.
*/
private void checkFieldTypes() {
for (final String fieldName : boosts.keySet()) {
final FieldType fieldType = req.getSchema().getFieldType(fieldName);
if (!(fieldType instanceof SirenField)) {
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,
"FieldType: " + fieldName + " (" + fieldType.getTypeName() + ") do not support NTriple Query");
}
}
}
/**
* Parse the Tuple query field operator params.
*
* If there is no field boost specified, use by default the disjunction
* operator.
*/
protected abstract void initTupleQueryFieldOperator(final SolrParams solrParams);
/**
* Initialise the Tuple query analyzer
*/
private Analyzer initAnalyzer() {
return new TokenizerChain(getTupleTokenizerFactory(), new TokenFilterFactory[0]);
}
/**
* Return the implementation for tokenizing the tuple, e.g., a {@link NTripleQueryTokenizerFactory};
* @return
*/
protected abstract BaseTokenizerFactory getTupleTokenizerFactory();
@Override
public Query parse() throws ParseException {
final Version version = req.getCore().getSolrConfig().luceneMatchVersion;
final Analyzer nqAnalyzer = this.initAnalyzer();
final DefaultOperatorAttribute.Operator defaultOp = this.getDefaultOperator();
if (boosts.size() == 1) {
final String field = boosts.keySet().iterator().next();
final Map datatypeConfig = this.initDatatypeConfig(field);
return parseTupleQuery(qstr, version, field, nqAnalyzer, datatypeConfig,
defaultOp);
}
else {
final Map> datatypeConfigs = this.initDatatypeConfigs(boosts);
return parseTupleQuery(qstr, version, boosts, nqAnalyzer, datatypeConfigs,
defaultOp);
}
}
/**
* Parse the tuple query
* @param qstr
* @param matchVersion
* @param field
* @param tupleAnalyzer
* @param datatypeConfig
* @param op
* @return
* @throws ParseException
*/
protected abstract Query parseTupleQuery(final String qstr,
final Version matchVersion,
final String field,
final Analyzer tupleAnalyzer,
final Map datatypeConfig,
final DefaultOperatorAttribute.Operator op)
throws ParseException;
/**
* Parse the tuple query
* @param qstr
* @param matchVersion
* @param boosts
* @param tupleAnalyzer
* @param datatypeConfigs
* @param op
* @param scattered
* @return
* @throws ParseException
*/
protected abstract Query parseTupleQuery(final String qstr,
final Version matchVersion,
final Map boosts,
final Analyzer tupleAnalyzer,
final Map> datatypeConfigs,
final DefaultOperatorAttribute.Operator op)
throws ParseException;
/**
* Retrieve the datatype query analyzers associated to this field
*/
private Map initDatatypeConfig(final String field) {
final Map datatypeConfig = new HashMap();
final SirenField fieldType = (SirenField) req.getSchema().getFieldType(field);
final Map datatypes = fieldType.getDatatypes();
for (final Entry e : datatypes.entrySet()) {
if (e.getValue().getQueryAnalyzer() == null) {
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,
"Configuration Error: No analyzer defined for type 'query' in " +
"datatype " + e.getKey());
}
datatypeConfig.put(e.getKey(), e.getValue().getQueryAnalyzer());
}
return datatypeConfig;
}
/**
* For each field in the boost map, retrieve the datatype query analyzers.
*/
private Map> initDatatypeConfigs(final Map boosts) {
final Map> datatypeConfigs = new HashMap>();
for (final String field : boosts.keySet()) {
datatypeConfigs.put(field, this.initDatatypeConfig(field));
}
return datatypeConfigs;
}
private DefaultOperatorAttribute.Operator getDefaultOperator() {
if (defaultOp == Operator.OR) {
return DefaultOperatorAttribute.Operator.OR;
}
return DefaultOperatorAttribute.Operator.AND;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy