/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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.
*/
using Lucene.Net.Analysis.Tokenattributes;
using Lucene.Net.Search;
using AttributeSource = Lucene.Net.Util.AttributeSource;
using NumericUtils = Lucene.Net.Util.NumericUtils;
using NumericField = Lucene.Net.Documents.NumericField;
// javadocs
namespace Lucene.Net.Analysis
{
/// Expert: This class provides a
/// for indexing numeric values that can be used by
/// or .
///
/// Note that for simple usage, is
/// recommended. disables norms and
/// term freqs, as they are not usually needed during
/// searching. If you need to change these settings, you
/// should use this class.
///
/// See for capabilities of fields
/// indexed numerically.
///
/// Here's an example usage, for an int field:
///
///
/// Field field = new Field(name, new NumericTokenStream(precisionStep).setIntValue(value));
/// field.setOmitNorms(true);
/// field.setOmitTermFreqAndPositions(true);
/// document.add(field);
///
///
/// For optimal performance, re-use the TokenStream and Field instance
/// for more than one document:
///
///
/// NumericTokenStream stream = new NumericTokenStream(precisionStep);
/// Field field = new Field(name, stream);
/// field.setOmitNorms(true);
/// field.setOmitTermFreqAndPositions(true);
/// Document document = new Document();
/// document.add(field);
///
/// for(all documents) {
/// stream.setIntValue(value)
/// writer.addDocument(document);
/// }
///
///
/// This stream is not intended to be used in analyzers;
/// it's more for iterating the different precisions during
/// indexing a specific numeric value.
///
/// NOTE: as token streams are only consumed once
/// the document is added to the index, if you index more
/// than one numeric field, use a separate NumericTokenStream
/// instance for each.
///
/// See for more details on the
/// precisionStep
/// parameter as well as how numeric fields work under the hood.
///
/// NOTE: This API is experimental and
/// might change in incompatible ways in the next release.
/// Since 2.9
///
public sealed class NumericTokenStream : TokenStream
{
private void InitBlock()
{
termAtt = AddAttribute();
typeAtt = AddAttribute();
posIncrAtt = AddAttribute();
}
/// The full precision token gets this token type assigned.
public const System.String TOKEN_TYPE_FULL_PREC = "fullPrecNumeric";
/// The lower precision tokens gets this token type assigned.
public const System.String TOKEN_TYPE_LOWER_PREC = "lowerPrecNumeric";
/// Creates a token stream for numeric values using the default precisionStep
/// (4). The stream is not yet initialized,
/// before using set a value using the various set???Value() methods.
///
public NumericTokenStream():this(NumericUtils.PRECISION_STEP_DEFAULT)
{
}
/// Creates a token stream for numeric values with the specified
/// precisionStep. The stream is not yet initialized,
/// before using set a value using the various set???Value() methods.
///
public NumericTokenStream(int precisionStep):base()
{
InitBlock();
this.precisionStep = precisionStep;
if (precisionStep < 1)
throw new System.ArgumentException("precisionStep must be >=1");
}
/// Expert: Creates a token stream for numeric values with the specified
/// precisionStep using the given .
/// The stream is not yet initialized,
/// before using set a value using the various set???Value() methods.
///
public NumericTokenStream(AttributeSource source, int precisionStep):base(source)
{
InitBlock();
this.precisionStep = precisionStep;
if (precisionStep < 1)
throw new System.ArgumentException("precisionStep must be >=1");
}
/// Expert: Creates a token stream for numeric values with the specified
/// precisionStep using the given
/// .
/// The stream is not yet initialized,
/// before using set a value using the various set???Value() methods.
///
public NumericTokenStream(AttributeFactory factory, int precisionStep):base(factory)
{
InitBlock();
this.precisionStep = precisionStep;
if (precisionStep < 1)
throw new System.ArgumentException("precisionStep must be >=1");
}
/// Initializes the token stream with the supplied long value.
/// the value, for which this TokenStream should enumerate tokens.
///
/// this instance, because of this you can use it the following way:
/// new Field(name, new NumericTokenStream(precisionStep).SetLongValue(value))
///
public NumericTokenStream SetLongValue(long value_Renamed)
{
this.value_Renamed = value_Renamed;
valSize = 64;
shift = 0;
return this;
}
/// Initializes the token stream with the supplied int value.
/// the value, for which this TokenStream should enumerate tokens.
///
/// this instance, because of this you can use it the following way:
/// new Field(name, new NumericTokenStream(precisionStep).SetIntValue(value))
///
public NumericTokenStream SetIntValue(int value_Renamed)
{
this.value_Renamed = (long) value_Renamed;
valSize = 32;
shift = 0;
return this;
}
/// Initializes the token stream with the supplied double value.
/// the value, for which this TokenStream should enumerate tokens.
///
/// this instance, because of this you can use it the following way:
/// new Field(name, new NumericTokenStream(precisionStep).SetDoubleValue(value))
///
public NumericTokenStream SetDoubleValue(double value_Renamed)
{
this.value_Renamed = NumericUtils.DoubleToSortableLong(value_Renamed);
valSize = 64;
shift = 0;
return this;
}
/// Initializes the token stream with the supplied float value.
/// the value, for which this TokenStream should enumerate tokens.
///
/// this instance, because of this you can use it the following way:
/// new Field(name, new NumericTokenStream(precisionStep).SetFloatValue(value))
///
public NumericTokenStream SetFloatValue(float value_Renamed)
{
this.value_Renamed = (long) NumericUtils.FloatToSortableInt(value_Renamed);
valSize = 32;
shift = 0;
return this;
}
// @Override
public override void Reset()
{
if (valSize == 0)
throw new System.SystemException("call set???Value() before usage");
shift = 0;
}
protected override void Dispose(bool disposing)
{
// Do nothing.
}
// @Override
public override bool IncrementToken()
{
if (valSize == 0)
throw new System.SystemException("call set???Value() before usage");
if (shift >= valSize)
return false;
ClearAttributes();
char[] buffer;
switch (valSize)
{
case 64:
buffer = termAtt.ResizeTermBuffer(NumericUtils.BUF_SIZE_LONG);
termAtt.SetTermLength(NumericUtils.LongToPrefixCoded(value_Renamed, shift, buffer));
break;
case 32:
buffer = termAtt.ResizeTermBuffer(NumericUtils.BUF_SIZE_INT);
termAtt.SetTermLength(NumericUtils.IntToPrefixCoded((int) value_Renamed, shift, buffer));
break;
default:
// should not happen
throw new System.ArgumentException("valSize must be 32 or 64");
}
typeAtt.Type = (shift == 0)?TOKEN_TYPE_FULL_PREC:TOKEN_TYPE_LOWER_PREC;
posIncrAtt.PositionIncrement = (shift == 0)?1:0;
shift += precisionStep;
return true;
}
// @Override
public override System.String ToString()
{
System.Text.StringBuilder sb = new System.Text.StringBuilder("(numeric,valSize=").Append(valSize);
sb.Append(",precisionStep=").Append(precisionStep).Append(')');
return sb.ToString();
}
// members
private ITermAttribute termAtt;
private ITypeAttribute typeAtt;
private IPositionIncrementAttribute posIncrAtt;
private int shift = 0, valSize = 0; // valSize==0 means not initialized
private readonly int precisionStep;
private long value_Renamed = 0L;
}
}