/**
* Copyright 2014 National University of Ireland, Galway.
*
* This file is part of the SIREn project. Project and contact information:
*
* https://github.com/rdelbru/SIREn
*
* 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 org.sindice.siren.solr.schema;
import java.util.Locale;
import java.util.Map;
import org.apache.solr.common.SolrException;
import org.apache.solr.schema.TrieField.TrieTypes;
import org.sindice.siren.analysis.DoubleNumericAnalyzer;
import org.sindice.siren.analysis.FloatNumericAnalyzer;
import org.sindice.siren.analysis.IntNumericAnalyzer;
import org.sindice.siren.analysis.LongNumericAnalyzer;
import org.sindice.siren.search.node.NodeNumericRangeQuery;
import org.sindice.siren.solr.analysis.DateNumericAnalyzer;
/**
* Provides a datatype to support for {@link NodeNumericRangeQuery}.
* It supports integer, float, long and double types.
* <p>
* For each number being of this datatype, multiple terms are generated as
* per the algorithm described in {@link NodeNumericRangeQuery}. The possible
* number of terms increases dramatically with lower precision steps.
* <p>
* Note that if you use a precisionStep of 32 for int/float and 64 for
* long/double, then multiple terms will not be generated, range search will be
* no faster than any other number field.
* <p>
* Expert: The query analyzer is used as a container for the numeric range query
* configuration, and should not be used to analyze query terms.
*/
public class TrieDatatype extends Datatype {
public static final int DEFAULT_PRECISION_STEP = 8;
protected int precisionStepArg = TrieDatatype.DEFAULT_PRECISION_STEP; // the one passed in or defaulted
protected int precisionStep; // normalized
protected TrieTypes type;
protected Object missingValue;
@Override
protected void init(final Map<String, String> args) {
final String p = args.remove("precisionStep");
if (p != null) {
precisionStepArg = Integer.parseInt(p);
}
// normalize the precisionStep
precisionStep = precisionStepArg;
if (precisionStep <= 0 || precisionStep >= 64) {
precisionStep = Integer.MAX_VALUE;
}
final String t = args.remove("type");
if (t != null) {
try {
type = TrieTypes.valueOf(t.toUpperCase(Locale.ROOT));
}
catch (final IllegalArgumentException e) {
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,
"Invalid datatype specified for field: " + args.get("name"), e);
}
}
this.initAnalyzers();
}
/**
* Initialise the numeric analyzers. The query analyzer is just used as a
* container of the numeric configuration, i.e., type and precision step.
*/
private void initAnalyzers() {
switch (type) {
case INTEGER:
queryAnalyzer = analyzer = new IntNumericAnalyzer(precisionStep);
break;
case LONG:
queryAnalyzer = analyzer = new LongNumericAnalyzer(precisionStep);
break;
case FLOAT:
queryAnalyzer = analyzer = new FloatNumericAnalyzer(precisionStep);
break;
case DOUBLE:
queryAnalyzer = analyzer = new DoubleNumericAnalyzer(precisionStep);
break;
case DATE:
queryAnalyzer = analyzer = new DateNumericAnalyzer(precisionStep);
break;
default:
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Unknown " +
"type for trie datatype");
}
}
/**
* @return the precisionStep used to index values by this datatype
*/
public int getPrecisionStep() {
return precisionStepArg;
}
/**
* @return the type of this datatype
*/
public TrieTypes getType() {
return type;
}
}