blob: c1d5bc90767b12efb7298bf289bea5557ae1b080 [file] [log] [blame]
using Lucene.Net.Queries.Function;
using Lucene.Net.Queries.Function.ValueSources;
using Lucene.Net.Search;
using System;
using System.Collections.Generic;
namespace Lucene.Net.Expressions
{
/*
* 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.
*/
/// <summary>
/// Simple class that binds expression variable names to
/// <see cref="Lucene.Net.Search.SortField"/>s or other
/// <see cref="Expression"/>s.
/// <para/>
/// Example usage:
/// <code>
/// SimpleBindings bindings = new SimpleBindings();
/// // document's text relevance score
/// bindings.Add(new SortField("_score", SortFieldType.SCORE));
/// // integer NumericDocValues field (or from FieldCache)
/// bindings.Add(new SortField("popularity", SortFieldType.INT));
/// // another expression
/// bindings.Add("recency", myRecencyExpression);
/// // create a sort field in reverse order
/// Sort sort = new Sort(expr.GetSortField(bindings, true));
/// </code>
/// @lucene.experimental
/// </summary>
public sealed class SimpleBindings : Bindings
{
internal readonly IDictionary<string, object> map = new Dictionary<string, object>();
/// <summary>
/// Creates a new empty <see cref="Bindings"/>
/// </summary>
public SimpleBindings() { }
/// <summary>Adds a <see cref="SortField"/> to the bindings.</summary>
/// <remarks>
/// Adds a <see cref="SortField"/> to the bindings.
/// <para/>
/// 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 <see cref="Expression"/> to the bindings.</summary>
/// <remarks>
/// Adds an <see cref="Expression"/> to the bindings.
/// <para/>
/// 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;
// LUCENENET NOTE: 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 SortFieldType.INT32:
{
return new Int32FieldSource(field.Field, (FieldCache.IInt32Parser)field.Parser);
}
case SortFieldType.INT64:
{
return new Int64FieldSource(field.Field, (FieldCache.IInt64Parser)field.Parser);
}
case SortFieldType.SINGLE:
{
return new SingleFieldSource(field.Field, (FieldCache.ISingleParser)field.Parser);
}
case SortFieldType.DOUBLE:
{
return new DoubleFieldSource(field.Field, (FieldCache.IDoubleParser)field.Parser);
}
case SortFieldType.SCORE:
{
return GetScoreValueSource();
}
default:
{
throw new NotSupportedException();
}
}
}
/// <summary>Traverses the graph of bindings, checking there are no cycles or missing references</summary>
/// <exception cref="ArgumentException">if the bindings is inconsistent</exception>
public void Validate()
{
foreach (object o in map.Values)
{
if (o is Expression)
{
Expression expr = (Expression)o;
expr.GetValueSource(this);
}
}
}
}
}