blob: 78f97d6a997a9b6eed891daf773392b0240075d5 [file] [log] [blame]
using System;
using System.Collections.Generic;
using Lucene.Net.Queries.Function;
using Lucene.Net.Queries.Function.ValueSources;
using Lucene.Net.Search;
namespace Lucene.Net.Expressions
{
/// <summary>
/// Simple class that binds expression variable names to
/// <see cref="Lucene.Net.Search.SortField">Lucene.Net.Search.SortField
/// </see>
/// s
/// or other
/// <see cref="Expression">Expression</see>
/// s.
/// <p>
/// Example usage:
/// <pre class="prettyprint">
/// SimpleBindings bindings = new SimpleBindings();
/// // document's text relevance score
/// bindings.add(new SortField("_score", SortField.Type.SCORE));
/// // integer NumericDocValues field (or from FieldCache)
/// bindings.add(new SortField("popularity", SortField.Type.INT));
/// // another expression
/// bindings.add("recency", myRecencyExpression);
/// // create a sort field in reverse order
/// Sort sort = new Sort(expr.getSortField(bindings, true));
/// </pre>
/// </summary>
/// <lucene.experimental></lucene.experimental>
public sealed class SimpleBindings : Bindings
{
internal readonly IDictionary<string, object> map = new Dictionary<string, object
>();
/// <summary>Adds a SortField to the bindings.</summary>
/// <remarks>
/// Adds a SortField to the bindings.
/// <p>
/// This can be used to reference a DocValuesField, a field from
/// FieldCache, the document's score, etc.
/// </remarks>
public void Add(SortField sortField)
{
map[sortField.Field] = sortField;
}
/// <summary>Adds an Expression to the bindings.</summary>
/// <remarks>
/// Adds an Expression to the bindings.
/// <p>
/// This can be used to reference expressions from other expressions.
/// </remarks>
public void Add(string name, Expression expression)
{
map[name] = expression;
}
public override ValueSource GetValueSource(string name)
{
object o;
//.NET Port. Directly looking up a missing key will throw a KeyNotFoundException
if (!map.TryGetValue(name, out o))
{
throw new ArgumentException("Invalid reference '" + name + "'");
}
var expression = o as Expression;
if (expression != null)
{
return expression.GetValueSource(this);
}
SortField field = (SortField)o;
switch (field.Type)
{
case SortField.Type_e.INT:
{
return new IntFieldSource(field.Field, (FieldCache.IIntParser)field.Parser);
}
case SortField.Type_e.LONG:
{
return new LongFieldSource(field.Field, (FieldCache.ILongParser)field.Parser);
}
case SortField.Type_e.FLOAT:
{
return new FloatFieldSource(field.Field, (FieldCache.IFloatParser)field.Parser);
}
case SortField.Type_e.DOUBLE:
{
return new DoubleFieldSource(field.Field, (FieldCache.IDoubleParser)field.Parser);
}
case SortField.Type_e.SCORE:
{
return GetScoreValueSource();
}
default:
{
throw new NotSupportedException();
}
}
}
/// <summary>Traverses the graph of bindings, checking there are no cycles or missing references
/// </summary>
/// <exception cref="System.ArgumentException">if the bindings is inconsistent</exception>
public void Validate()
{
foreach (object o in map.Values)
{
if (o is Expression)
{
Expression expr = (Expression)o;
try
{
expr.GetValueSource(this);
}
catch (StackOverflowException)
{
throw new ArgumentException("Recursion Error: Cycle detected originating in (" + expr.sourceText + ")");
}
}
}
}
}
}