blob: 672ec6b12f84cbdf50f6d7e0613aba3476266fbd [file] [log] [blame]
/*
* 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 System;
using Lucene.Net.Index;
using Lucene.Net.Search;
using Lucene.Net.Util;
using Lucene.Net.Util.Mutable;
namespace Lucene.Net.Queries.Function.DocValues
{
/// <summary>
/// Serves as base class for FunctionValues based on DocTermsIndex.
/// @lucene.internal
/// </summary>
public abstract class DocTermsIndexDocValues : FunctionValues
{
protected internal readonly SortedDocValues termsIndex;
protected internal readonly ValueSource vs;
protected internal readonly MutableValueStr val = new MutableValueStr();
protected internal readonly BytesRef spare = new BytesRef();
protected internal readonly CharsRef spareChars = new CharsRef();
protected DocTermsIndexDocValues(ValueSource vs, AtomicReaderContext context, string field)
{
try
{
termsIndex = FieldCache.DEFAULT.GetTermsIndex(context.AtomicReader, field);
}
catch (Exception e)
{
throw new DocTermsIndexException(field, e);
}
this.vs = vs;
}
protected internal abstract string toTerm(string readableValue);
public override bool Exists(int doc)
{
return OrdVal(doc) >= 0;
}
public override int OrdVal(int doc)
{
return termsIndex.GetOrd(doc);
}
public override int NumOrd()
{
return termsIndex.ValueCount;
}
public override bool BytesVal(int doc, BytesRef target)
{
termsIndex.Get(doc, target);
return target.Length > 0;
}
public override string StrVal(int doc)
{
termsIndex.Get(doc, spare);
if (spare.Length == 0)
{
return null;
}
UnicodeUtil.UTF8toUTF16(spare, spareChars);
return spareChars.ToString();
}
public override bool BoolVal(int doc)
{
return Exists(doc);
}
public override abstract object ObjectVal(int doc); // force subclasses to override
public override ValueSourceScorer GetRangeScorer(IndexReader reader, string lowerVal, string upperVal, bool includeLower, bool includeUpper)
{
// TODO: are lowerVal and upperVal in indexed form or not?
lowerVal = lowerVal == null ? null : toTerm(lowerVal);
upperVal = upperVal == null ? null : toTerm(upperVal);
int lower = int.MinValue;
if (lowerVal != null)
{
lower = termsIndex.LookupTerm(new BytesRef(lowerVal));
if (lower < 0)
{
lower = -lower - 1;
}
else if (!includeLower)
{
lower++;
}
}
int upper = int.MaxValue;
if (upperVal != null)
{
upper = termsIndex.LookupTerm(new BytesRef(upperVal));
if (upper < 0)
{
upper = -upper - 2;
}
else if (!includeUpper)
{
upper--;
}
}
int ll = lower;
int uu = upper;
return new ValueSourceScorerAnonymousInnerClassHelper(this, reader, this, ll, uu);
}
private class ValueSourceScorerAnonymousInnerClassHelper : ValueSourceScorer
{
private readonly DocTermsIndexDocValues outerInstance;
private int ll;
private int uu;
public ValueSourceScorerAnonymousInnerClassHelper(DocTermsIndexDocValues outerInstance, IndexReader reader,
DocTermsIndexDocValues @this, int ll, int uu)
: base(reader, @this)
{
this.outerInstance = outerInstance;
this.ll = ll;
this.uu = uu;
}
public override bool MatchesValue(int doc)
{
int ord = outerInstance.termsIndex.GetOrd(doc);
return ord >= ll && ord <= uu;
}
}
public override string ToString(int doc)
{
return vs.Description + '=' + StrVal(doc);
}
public override AbstractValueFiller ValueFiller
{
get
{
return new ValueFillerAnonymousInnerClassHelper(this);
}
}
private class ValueFillerAnonymousInnerClassHelper : AbstractValueFiller
{
private readonly DocTermsIndexDocValues outerInstance;
public ValueFillerAnonymousInnerClassHelper(DocTermsIndexDocValues outerInstance)
{
this.outerInstance = outerInstance;
mval = new MutableValueStr();
}
private readonly MutableValueStr mval;
public override MutableValue Value
{
get
{
return mval;
}
}
public override void FillValue(int doc)
{
int ord = outerInstance.termsIndex.GetOrd(doc);
if (ord == -1)
{
mval.Value.Bytes = BytesRef.EMPTY_BYTES;
mval.Value.Offset = 0;
mval.Value.Length = 0;
mval.Exists = false;
}
else
{
outerInstance.termsIndex.LookupOrd(ord, mval.Value);
mval.Exists = true;
}
}
}
/// <summary>
/// Custom Exception to be thrown when the DocTermsIndex for a field cannot be generated
/// </summary>
public sealed class DocTermsIndexException : Exception
{
public DocTermsIndexException(string fieldName, Exception cause)
: base("Can't initialize DocTermsIndex to generate (function) FunctionValues for field: " + fieldName, cause)
{
}
}
}
}