fixed SPRNET-1155 - removed dateLiteral from antlr grammar and replaced with IMethodCallProcessor strategy in MethodNode
This commit is contained in:
@@ -1,84 +0,0 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright <20> 2002-2005 the original author or authors.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Runtime.Serialization;
|
||||
using Spring.Expressions.Parser.antlr.collections;
|
||||
|
||||
namespace Spring.Expressions
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents parsed node in the navigation expression.
|
||||
/// </summary>
|
||||
/// <author>Aleksandar Seovic</author>
|
||||
[Serializable]
|
||||
public class DateLiteralNode : BaseNode
|
||||
{
|
||||
private object nodeValue;
|
||||
|
||||
/// <summary>
|
||||
/// Create a new instance
|
||||
/// </summary>
|
||||
public DateLiteralNode():base()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new instance from SerializationInfo
|
||||
/// </summary>
|
||||
protected DateLiteralNode(SerializationInfo info, StreamingContext context)
|
||||
: base(info, context)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns node's value for the given context.
|
||||
/// </summary>
|
||||
/// <param name="context">Context to evaluate expressions against.</param>
|
||||
/// <param name="evalContext">Current expression evaluation context.</param>
|
||||
/// <returns>Node's value.</returns>
|
||||
protected override object Get(object context, EvaluationContext evalContext)
|
||||
{
|
||||
if (nodeValue == null)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
if (nodeValue == null)
|
||||
{
|
||||
AST dateString = this.getFirstChild();
|
||||
if (getNumberOfChildren() == 2)
|
||||
{
|
||||
AST dateFormat = dateString.getNextSibling();
|
||||
nodeValue =
|
||||
DateTime.ParseExact(dateString.getText(), dateFormat.getText(),
|
||||
CultureInfo.InvariantCulture);
|
||||
}
|
||||
else
|
||||
{
|
||||
nodeValue = DateTime.Parse(dateString.getText());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nodeValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -154,7 +154,7 @@ node :
|
||||
| firstSelection
|
||||
| lastSelection
|
||||
| exprList
|
||||
| DOT!
|
||||
| DOT!
|
||||
)+
|
||||
;
|
||||
|
||||
@@ -173,15 +173,17 @@ localFunctionOrVar
|
||||
| localVar
|
||||
;
|
||||
|
||||
localFunction : DOLLAR! ID^ <AST = Spring.Expressions.LocalFunctionNode> methodArgs
|
||||
localFunction
|
||||
: DOLLAR! ID^ <AST = Spring.Expressions.LocalFunctionNode> methodArgs
|
||||
;
|
||||
|
||||
localVar : DOLLAR! ID^ <AST = Spring.Expressions.LocalVariableNode>;
|
||||
localVar
|
||||
: DOLLAR! ID^ <AST = Spring.Expressions.LocalVariableNode>
|
||||
;
|
||||
|
||||
methodOrProperty
|
||||
: (ID LPAREN)=>
|
||||
ID^ <AST = Spring.Expressions.MethodNode> methodArgs
|
||||
| property
|
||||
: (ID LPAREN)=> ID^ <AST = Spring.Expressions.MethodNode> methodArgs
|
||||
| property
|
||||
;
|
||||
|
||||
methodArgs
|
||||
@@ -301,7 +303,6 @@ literal
|
||||
| REAL_LITERAL <AST = Spring.Expressions.RealLiteralNode>
|
||||
| STRING_LITERAL <AST = Spring.Expressions.StringLiteralNode>
|
||||
| boolLiteral
|
||||
| dateLiteral
|
||||
;
|
||||
|
||||
boolLiteral
|
||||
@@ -309,11 +310,6 @@ boolLiteral
|
||||
| FALSE <AST = Spring.Expressions.BooleanLiteralNode>
|
||||
;
|
||||
|
||||
dateLiteral
|
||||
: "date"^ <AST = Spring.Expressions.DateLiteralNode>
|
||||
LPAREN! STRING_LITERAL (COMMA! STRING_LITERAL)? RPAREN!
|
||||
;
|
||||
|
||||
relationalOperator
|
||||
: EQUAL
|
||||
| NOT_EQUAL
|
||||
@@ -329,6 +325,7 @@ relationalOperator
|
||||
;
|
||||
|
||||
|
||||
|
||||
class ExpressionLexer extends Lexer;
|
||||
|
||||
options {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#region License
|
||||
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright <20> 2002-2005 the original author or authors.
|
||||
*
|
||||
@@ -14,258 +14,260 @@
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Serialization;
|
||||
using Spring.Expressions.Processors;
|
||||
using Spring.Util;
|
||||
using Spring.Reflection.Dynamic;
|
||||
|
||||
namespace Spring.Expressions
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents parsed method node in the navigation expression.
|
||||
/// </summary>
|
||||
/// <author>Aleksandar Seovic</author>
|
||||
[Serializable]
|
||||
public class MethodNode : NodeWithArguments
|
||||
{
|
||||
private const BindingFlags BINDING_FLAGS
|
||||
= BindingFlags.Public | BindingFlags.NonPublic
|
||||
| BindingFlags.Instance | BindingFlags.Static
|
||||
| BindingFlags.IgnoreCase;
|
||||
|
||||
private static readonly IDictionary collectionProcessorMap = new Hashtable();
|
||||
|
||||
private bool initialized = false;
|
||||
private bool isParamArray = false;
|
||||
private Type paramArrayType;
|
||||
private int argumentCount;
|
||||
private SafeMethod method;
|
||||
private int methodHash;
|
||||
private bool isCollectionProcessor = false;
|
||||
private ICollectionProcessor collectionProcessor;
|
||||
|
||||
/// <summary>
|
||||
/// Static constructor. Initializes a map of special collection processor methods.
|
||||
/// </summary>
|
||||
static MethodNode()
|
||||
{
|
||||
collectionProcessorMap.Add("count", new CountAggregator());
|
||||
collectionProcessorMap.Add("sum", new SumAggregator());
|
||||
collectionProcessorMap.Add("max", new MaxAggregator());
|
||||
collectionProcessorMap.Add("min", new MinAggregator());
|
||||
collectionProcessorMap.Add("average", new AverageAggregator());
|
||||
collectionProcessorMap.Add("sort", new SortProcessor());
|
||||
collectionProcessorMap.Add("orderBy", new OrderByProcessor());
|
||||
collectionProcessorMap.Add("distinct", new DistinctProcessor());
|
||||
collectionProcessorMap.Add("nonNull", new NonNullProcessor());
|
||||
collectionProcessorMap.Add("convert", new ConversionProcessor());
|
||||
collectionProcessorMap.Add("reverse", new ReverseProcessor());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new instance
|
||||
/// </summary>
|
||||
public MethodNode()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new instance from SerializationInfo
|
||||
/// </summary>
|
||||
protected MethodNode(SerializationInfo info, StreamingContext context)
|
||||
: base(info, context)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns node's value for the given context.
|
||||
/// </summary>
|
||||
/// <param name="context">Context to evaluate expressions against.</param>
|
||||
/// <param name="evalContext">Current expression evaluation context.</param>
|
||||
/// <returns>Node's value.</returns>
|
||||
protected override object Get(object context, EvaluationContext evalContext)
|
||||
{
|
||||
object[] argValues = ResolveArguments(evalContext);
|
||||
|
||||
ICollectionProcessor localCollectionProcessor = null;
|
||||
SafeMethod localMethod = null;
|
||||
|
||||
// resolve method, if necessary
|
||||
lock (this)
|
||||
{
|
||||
if (!isCollectionProcessor)
|
||||
{
|
||||
if ((context == null || context is ICollection))
|
||||
{
|
||||
string methodName = this.getText();
|
||||
|
||||
// predefined collection processor?
|
||||
collectionProcessor = (ICollectionProcessor)collectionProcessorMap[methodName];
|
||||
isCollectionProcessor = (collectionProcessor != null);
|
||||
localCollectionProcessor = collectionProcessor;
|
||||
|
||||
if (!isCollectionProcessor && evalContext.Variables != null)
|
||||
{
|
||||
localCollectionProcessor = evalContext.Variables[methodName] as ICollectionProcessor;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
localCollectionProcessor = collectionProcessor;
|
||||
}
|
||||
|
||||
if (localCollectionProcessor == null)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
throw new ArgumentNullException("Context for method invocation cannot be null.");
|
||||
}
|
||||
|
||||
// calculate checksum, if the cached method matches the current context
|
||||
if (initialized)
|
||||
{
|
||||
int calculatedHash = CalculateMethodHash(context.GetType(), argValues);
|
||||
initialized = (calculatedHash == methodHash);
|
||||
}
|
||||
|
||||
if (!initialized)
|
||||
{
|
||||
string methodName = this.getText();
|
||||
Initialize(methodName, argValues, context);
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
localMethod = method;
|
||||
}
|
||||
}
|
||||
|
||||
// invoke method
|
||||
if (localCollectionProcessor != null)
|
||||
{
|
||||
return localCollectionProcessor.Process((ICollection)context, argValues);
|
||||
}
|
||||
else
|
||||
{
|
||||
object[] paramValues = (isParamArray ? ReflectionUtils.PackageParamArray(argValues, argumentCount, paramArrayType) : argValues);
|
||||
return localMethod.Invoke(context, paramValues);
|
||||
}
|
||||
}
|
||||
|
||||
private int CalculateMethodHash(Type contextType, object[] argValues)
|
||||
{
|
||||
int hash = contextType.GetHashCode();
|
||||
for (int i = 0; i < argValues.Length; i++)
|
||||
{
|
||||
object arg = argValues[i];
|
||||
if (arg != null) hash += s_primes[i] * arg.GetType().GetHashCode();
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
private void Initialize(string methodName, object[] argValues, object context)
|
||||
{
|
||||
Type contextType = (context is Type ? context as Type : context.GetType());
|
||||
|
||||
// check the context type first
|
||||
MethodInfo mi = GetBestMethod(contextType, methodName, BINDING_FLAGS, argValues);
|
||||
|
||||
// if not found, probe the Type's type
|
||||
if (mi == null)
|
||||
{
|
||||
mi = GetBestMethod(typeof(Type), methodName, BINDING_FLAGS, argValues);
|
||||
}
|
||||
|
||||
if (mi == null)
|
||||
{
|
||||
throw new ArgumentException(
|
||||
string.Format("Method '{0}' with the specified number and types of arguments does not exist.",
|
||||
methodName));
|
||||
}
|
||||
else
|
||||
{
|
||||
ParameterInfo[] parameters = mi.GetParameters();
|
||||
if (parameters.Length > 0)
|
||||
{
|
||||
ParameterInfo lastParameter = parameters[parameters.Length - 1];
|
||||
isParamArray = lastParameter.GetCustomAttributes(typeof(ParamArrayAttribute), false).Length > 0;
|
||||
if (isParamArray)
|
||||
{
|
||||
paramArrayType = lastParameter.ParameterType.GetElementType();
|
||||
argumentCount = parameters.Length;
|
||||
}
|
||||
}
|
||||
|
||||
method = new SafeMethod(mi);
|
||||
methodHash = CalculateMethodHash(contextType, argValues);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the best method given the name, argument values, for a given type.
|
||||
/// </summary>
|
||||
/// <param name="type">The type on which to search for the method.</param>
|
||||
/// <param name="methodName">Name of the method.</param>
|
||||
/// <param name="bindingFlags">The binding flags.</param>
|
||||
/// <param name="argValues">The arg values.</param>
|
||||
/// <returns>Best matching method or null if none found.</returns>
|
||||
public static MethodInfo GetBestMethod(Type type, string methodName, BindingFlags bindingFlags, object[] argValues)
|
||||
{
|
||||
MethodInfo mi = null;
|
||||
try
|
||||
{
|
||||
mi = type.GetMethod(methodName, bindingFlags | BindingFlags.FlattenHierarchy);
|
||||
}
|
||||
catch (AmbiguousMatchException)
|
||||
{
|
||||
|
||||
MethodInfo[] overloads = GetCandidateMethods(type, methodName, bindingFlags, argValues.Length);
|
||||
if (overloads.Length > 0)
|
||||
{
|
||||
mi = ReflectionUtils.GetMethodByArgumentValues(overloads, argValues);
|
||||
}
|
||||
}
|
||||
return mi;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static MethodInfo[] GetCandidateMethods(Type type, string methodName, BindingFlags bindingFlags, int argCount)
|
||||
{
|
||||
MethodInfo[] methods = type.GetMethods(bindingFlags | BindingFlags.FlattenHierarchy);
|
||||
ArrayList matches = new ArrayList();
|
||||
|
||||
foreach (MethodInfo method in methods)
|
||||
{
|
||||
if (method.Name == methodName)
|
||||
{
|
||||
ParameterInfo[] parameters = method.GetParameters();
|
||||
if (parameters.Length == argCount)
|
||||
{
|
||||
matches.Add(method);
|
||||
}
|
||||
else if (parameters.Length > 0)
|
||||
{
|
||||
ParameterInfo lastParameter = parameters[parameters.Length - 1];
|
||||
if (lastParameter.GetCustomAttributes(typeof(ParamArrayAttribute), false).Length > 0)
|
||||
{
|
||||
matches.Add(method);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (MethodInfo[])matches.ToArray(typeof(MethodInfo));
|
||||
}
|
||||
|
||||
// used to calculate signature hash while caring for arg positions
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Serialization;
|
||||
using Spring.Expressions.Processors;
|
||||
using Spring.Util;
|
||||
using Spring.Reflection.Dynamic;
|
||||
|
||||
namespace Spring.Expressions
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents parsed method node in the navigation expression.
|
||||
/// </summary>
|
||||
/// <author>Aleksandar Seovic</author>
|
||||
[Serializable]
|
||||
public class MethodNode : NodeWithArguments
|
||||
{
|
||||
private const BindingFlags BINDING_FLAGS
|
||||
= BindingFlags.Public | BindingFlags.NonPublic
|
||||
| BindingFlags.Instance | BindingFlags.Static
|
||||
| BindingFlags.IgnoreCase;
|
||||
|
||||
private static readonly IDictionary collectionProcessorMap = new Hashtable();
|
||||
private static readonly IDictionary extensionMethodProcessorMap = new Hashtable();
|
||||
|
||||
private bool initialized = false;
|
||||
private bool cachedIsParamArray = false;
|
||||
private Type paramArrayType;
|
||||
private int argumentCount;
|
||||
private SafeMethod cachedInstanceMethod;
|
||||
private int cachedInstanceMethodHash;
|
||||
|
||||
/// <summary>
|
||||
/// Static constructor. Initializes a map of special collection processor methods.
|
||||
/// </summary>
|
||||
static MethodNode()
|
||||
{
|
||||
collectionProcessorMap.Add("count", new CountAggregator());
|
||||
collectionProcessorMap.Add("sum", new SumAggregator());
|
||||
collectionProcessorMap.Add("max", new MaxAggregator());
|
||||
collectionProcessorMap.Add("min", new MinAggregator());
|
||||
collectionProcessorMap.Add("average", new AverageAggregator());
|
||||
collectionProcessorMap.Add("sort", new SortProcessor());
|
||||
collectionProcessorMap.Add("orderBy", new OrderByProcessor());
|
||||
collectionProcessorMap.Add("distinct", new DistinctProcessor());
|
||||
collectionProcessorMap.Add("nonNull", new NonNullProcessor());
|
||||
collectionProcessorMap.Add("reverse", new ReverseProcessor());
|
||||
collectionProcessorMap.Add("convert", new ConversionProcessor());
|
||||
|
||||
extensionMethodProcessorMap.Add("date", new DateConversionProcessor());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new instance
|
||||
/// </summary>
|
||||
public MethodNode()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new instance from SerializationInfo
|
||||
/// </summary>
|
||||
protected MethodNode(SerializationInfo info, StreamingContext context)
|
||||
: base(info, context)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns node's value for the given context.
|
||||
/// </summary>
|
||||
/// <param name="context">Context to evaluate expressions against.</param>
|
||||
/// <param name="evalContext">Current expression evaluation context.</param>
|
||||
/// <returns>Node's value.</returns>
|
||||
protected override object Get(object context, EvaluationContext evalContext)
|
||||
{
|
||||
string methodName = this.getText();
|
||||
object[] argValues = ResolveArguments(evalContext);
|
||||
|
||||
// resolve method, if necessary
|
||||
lock (this)
|
||||
{
|
||||
// check if it is a collection and the methodname denotes a collection processor
|
||||
if ((context == null || context is ICollection))
|
||||
{
|
||||
ICollectionProcessor localCollectionProcessor;
|
||||
// predefined collection processor?
|
||||
localCollectionProcessor = (ICollectionProcessor) collectionProcessorMap[methodName];
|
||||
|
||||
// user-defined collection processor?
|
||||
if (localCollectionProcessor == null && evalContext.Variables != null)
|
||||
{
|
||||
localCollectionProcessor = evalContext.Variables[methodName] as ICollectionProcessor;
|
||||
}
|
||||
|
||||
if (localCollectionProcessor != null)
|
||||
{
|
||||
return localCollectionProcessor.Process((ICollection) context, argValues);
|
||||
}
|
||||
}
|
||||
|
||||
// try extension methods
|
||||
IMethodCallProcessor methodCallProcessor = (IMethodCallProcessor)extensionMethodProcessorMap[methodName];
|
||||
{
|
||||
// user-defined extension method processor?
|
||||
if (methodCallProcessor == null && evalContext.Variables != null)
|
||||
{
|
||||
methodCallProcessor = evalContext.Variables[methodName] as IMethodCallProcessor;
|
||||
}
|
||||
|
||||
if (methodCallProcessor != null)
|
||||
{
|
||||
return methodCallProcessor.Process(context, argValues);
|
||||
}
|
||||
}
|
||||
|
||||
// try instance method
|
||||
if (context != null)
|
||||
{
|
||||
// calculate checksum, if the cached method matches the current context
|
||||
if (initialized)
|
||||
{
|
||||
int calculatedHash = CalculateMethodHash(context.GetType(), argValues);
|
||||
initialized = (calculatedHash == cachedInstanceMethodHash);
|
||||
}
|
||||
|
||||
if (!initialized)
|
||||
{
|
||||
Initialize(methodName, argValues, context);
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
if (cachedInstanceMethod != null)
|
||||
{
|
||||
object[] paramValues = (cachedIsParamArray)
|
||||
? ReflectionUtils.PackageParamArray(argValues, argumentCount, paramArrayType)
|
||||
: argValues;
|
||||
return cachedInstanceMethod.Invoke(context, paramValues);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw new ArgumentException(string.Format("Method '{0}' with the specified number and types of arguments does not exist.", methodName));
|
||||
}
|
||||
|
||||
private int CalculateMethodHash(Type contextType, object[] argValues)
|
||||
{
|
||||
int hash = contextType.GetHashCode();
|
||||
for (int i = 0; i < argValues.Length; i++)
|
||||
{
|
||||
object arg = argValues[i];
|
||||
if (arg != null)
|
||||
hash += s_primes[i] * arg.GetType().GetHashCode();
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
private void Initialize(string methodName, object[] argValues, object context)
|
||||
{
|
||||
Type contextType = (context is Type ? context as Type : context.GetType());
|
||||
|
||||
// check the context type first
|
||||
MethodInfo mi = GetBestMethod(contextType, methodName, BINDING_FLAGS, argValues);
|
||||
|
||||
// if not found, probe the Type's type
|
||||
if (mi == null)
|
||||
{
|
||||
mi = GetBestMethod(typeof(Type), methodName, BINDING_FLAGS, argValues);
|
||||
}
|
||||
|
||||
if (mi == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
ParameterInfo[] parameters = mi.GetParameters();
|
||||
if (parameters.Length > 0)
|
||||
{
|
||||
ParameterInfo lastParameter = parameters[parameters.Length - 1];
|
||||
cachedIsParamArray = lastParameter.GetCustomAttributes(typeof(ParamArrayAttribute), false).Length > 0;
|
||||
if (cachedIsParamArray)
|
||||
{
|
||||
paramArrayType = lastParameter.ParameterType.GetElementType();
|
||||
argumentCount = parameters.Length;
|
||||
}
|
||||
}
|
||||
|
||||
cachedInstanceMethod = new SafeMethod(mi);
|
||||
cachedInstanceMethodHash = CalculateMethodHash(contextType, argValues);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the best method given the name, argument values, for a given type.
|
||||
/// </summary>
|
||||
/// <param name="type">The type on which to search for the method.</param>
|
||||
/// <param name="methodName">Name of the method.</param>
|
||||
/// <param name="bindingFlags">The binding flags.</param>
|
||||
/// <param name="argValues">The arg values.</param>
|
||||
/// <returns>Best matching method or null if none found.</returns>
|
||||
public static MethodInfo GetBestMethod(Type type, string methodName, BindingFlags bindingFlags, object[] argValues)
|
||||
{
|
||||
MethodInfo mi = null;
|
||||
try
|
||||
{
|
||||
mi = type.GetMethod(methodName, bindingFlags | BindingFlags.FlattenHierarchy);
|
||||
}
|
||||
catch (AmbiguousMatchException)
|
||||
{
|
||||
|
||||
MethodInfo[] overloads = GetCandidateMethods(type, methodName, bindingFlags, argValues.Length);
|
||||
if (overloads.Length > 0)
|
||||
{
|
||||
mi = ReflectionUtils.GetMethodByArgumentValues(overloads, argValues);
|
||||
}
|
||||
}
|
||||
return mi;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static MethodInfo[] GetCandidateMethods(Type type, string methodName, BindingFlags bindingFlags, int argCount)
|
||||
{
|
||||
MethodInfo[] methods = type.GetMethods(bindingFlags | BindingFlags.FlattenHierarchy);
|
||||
ArrayList matches = new ArrayList();
|
||||
|
||||
foreach (MethodInfo method in methods)
|
||||
{
|
||||
if (method.Name == methodName)
|
||||
{
|
||||
ParameterInfo[] parameters = method.GetParameters();
|
||||
if (parameters.Length == argCount)
|
||||
{
|
||||
matches.Add(method);
|
||||
}
|
||||
else if (parameters.Length > 0)
|
||||
{
|
||||
ParameterInfo lastParameter = parameters[parameters.Length - 1];
|
||||
if (lastParameter.GetCustomAttributes(typeof(ParamArrayAttribute), false).Length > 0)
|
||||
{
|
||||
matches.Add(method);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (MethodInfo[])matches.ToArray(typeof(MethodInfo));
|
||||
}
|
||||
|
||||
// used to calculate signature hash while caring for arg positions
|
||||
private static readonly int[] s_primes =
|
||||
{
|
||||
17, 19, 23, 29
|
||||
@@ -281,6 +283,6 @@ namespace Spring.Expressions
|
||||
, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601
|
||||
, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659
|
||||
, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,25 +84,24 @@ namespace Spring.Expressions.Parser
|
||||
public const int INTEGER_LITERAL = 51;
|
||||
public const int HEXADECIMAL_INTEGER_LITERAL = 52;
|
||||
public const int REAL_LITERAL = 53;
|
||||
public const int LITERAL_date = 54;
|
||||
public const int EQUAL = 55;
|
||||
public const int NOT_EQUAL = 56;
|
||||
public const int LESS_THAN = 57;
|
||||
public const int LESS_THAN_OR_EQUAL = 58;
|
||||
public const int GREATER_THAN = 59;
|
||||
public const int GREATER_THAN_OR_EQUAL = 60;
|
||||
public const int WS = 61;
|
||||
public const int BACKTICK = 62;
|
||||
public const int BACKSLASH = 63;
|
||||
public const int DOT_ESCAPED = 64;
|
||||
public const int APOS = 65;
|
||||
public const int NUMERIC_LITERAL = 66;
|
||||
public const int DECIMAL_DIGIT = 67;
|
||||
public const int INTEGER_TYPE_SUFFIX = 68;
|
||||
public const int HEX_DIGIT = 69;
|
||||
public const int EXPONENT_PART = 70;
|
||||
public const int SIGN = 71;
|
||||
public const int REAL_TYPE_SUFFIX = 72;
|
||||
public const int EQUAL = 54;
|
||||
public const int NOT_EQUAL = 55;
|
||||
public const int LESS_THAN = 56;
|
||||
public const int LESS_THAN_OR_EQUAL = 57;
|
||||
public const int GREATER_THAN = 58;
|
||||
public const int GREATER_THAN_OR_EQUAL = 59;
|
||||
public const int WS = 60;
|
||||
public const int BACKTICK = 61;
|
||||
public const int BACKSLASH = 62;
|
||||
public const int DOT_ESCAPED = 63;
|
||||
public const int APOS = 64;
|
||||
public const int NUMERIC_LITERAL = 65;
|
||||
public const int DECIMAL_DIGIT = 66;
|
||||
public const int INTEGER_TYPE_SUFFIX = 67;
|
||||
public const int HEX_DIGIT = 68;
|
||||
public const int EXPONENT_PART = 69;
|
||||
public const int SIGN = 70;
|
||||
public const int REAL_TYPE_SUFFIX = 71;
|
||||
|
||||
|
||||
// CLOVER:OFF
|
||||
@@ -138,7 +137,6 @@ namespace Spring.Expressions.Parser
|
||||
literals.Add("is", 12);
|
||||
literals.Add("like", 14);
|
||||
literals.Add("new", 49);
|
||||
literals.Add("date", 54);
|
||||
literals.Add("false", 6);
|
||||
}
|
||||
|
||||
@@ -1010,11 +1008,11 @@ tryAgain:
|
||||
}
|
||||
else
|
||||
{
|
||||
goto _loop163_breakloop;
|
||||
goto _loop161_breakloop;
|
||||
}
|
||||
|
||||
}
|
||||
_loop163_breakloop: ;
|
||||
_loop161_breakloop: ;
|
||||
} // ( ... )*
|
||||
_saveIndex = text.Length;
|
||||
mQUOTE(false);
|
||||
@@ -1127,11 +1125,11 @@ _loop163_breakloop: ;
|
||||
}
|
||||
default:
|
||||
{
|
||||
goto _loop168_breakloop;
|
||||
goto _loop166_breakloop;
|
||||
}
|
||||
}
|
||||
}
|
||||
_loop168_breakloop: ;
|
||||
_loop166_breakloop: ;
|
||||
} // ( ... )*
|
||||
_ttype = testLiteralsTable(_ttype);
|
||||
if (_createToken && (null == _token) && (_ttype != Token.SKIP))
|
||||
@@ -1147,11 +1145,11 @@ _loop168_breakloop: ;
|
||||
int _ttype; IToken _token=null; int _begin=text.Length;
|
||||
_ttype = NUMERIC_LITERAL;
|
||||
|
||||
bool synPredMatched171 = false;
|
||||
bool synPredMatched169 = false;
|
||||
if (((cached_LA1=='.') && ((cached_LA2 >= '0' && cached_LA2 <= '9'))))
|
||||
{
|
||||
int _m171 = mark();
|
||||
synPredMatched171 = true;
|
||||
int _m169 = mark();
|
||||
synPredMatched169 = true;
|
||||
inputState.guessing++;
|
||||
try {
|
||||
{
|
||||
@@ -1161,16 +1159,16 @@ _loop168_breakloop: ;
|
||||
}
|
||||
catch (RecognitionException)
|
||||
{
|
||||
synPredMatched171 = false;
|
||||
synPredMatched169 = false;
|
||||
}
|
||||
rewind(_m171);
|
||||
rewind(_m169);
|
||||
inputState.guessing--;
|
||||
}
|
||||
if ( synPredMatched171 )
|
||||
if ( synPredMatched169 )
|
||||
{
|
||||
match('.');
|
||||
{ // ( ... )+
|
||||
int _cnt173=0;
|
||||
int _cnt171=0;
|
||||
for (;;)
|
||||
{
|
||||
if (((cached_LA1 >= '0' && cached_LA1 <= '9')))
|
||||
@@ -1179,12 +1177,12 @@ _loop168_breakloop: ;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_cnt173 >= 1) { goto _loop173_breakloop; } else { throw new NoViableAltForCharException(cached_LA1, getFilename(), getLine(), getColumn());; }
|
||||
if (_cnt171 >= 1) { goto _loop171_breakloop; } else { throw new NoViableAltForCharException(cached_LA1, getFilename(), getLine(), getColumn());; }
|
||||
}
|
||||
|
||||
_cnt173++;
|
||||
_cnt171++;
|
||||
}
|
||||
_loop173_breakloop: ;
|
||||
_loop171_breakloop: ;
|
||||
} // ( ... )+
|
||||
{
|
||||
if ((cached_LA1=='E'||cached_LA1=='e'))
|
||||
@@ -1210,16 +1208,16 @@ _loop173_breakloop: ;
|
||||
}
|
||||
}
|
||||
else {
|
||||
bool synPredMatched179 = false;
|
||||
bool synPredMatched177 = false;
|
||||
if ((((cached_LA1 >= '0' && cached_LA1 <= '9')) && (tokenSet_1_.member(cached_LA2))))
|
||||
{
|
||||
int _m179 = mark();
|
||||
synPredMatched179 = true;
|
||||
int _m177 = mark();
|
||||
synPredMatched177 = true;
|
||||
inputState.guessing++;
|
||||
try {
|
||||
{
|
||||
{ // ( ... )+
|
||||
int _cnt178=0;
|
||||
int _cnt176=0;
|
||||
for (;;)
|
||||
{
|
||||
if (((cached_LA1 >= '0' && cached_LA1 <= '9')))
|
||||
@@ -1228,12 +1226,12 @@ _loop173_breakloop: ;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_cnt178 >= 1) { goto _loop178_breakloop; } else { throw new NoViableAltForCharException(cached_LA1, getFilename(), getLine(), getColumn());; }
|
||||
if (_cnt176 >= 1) { goto _loop176_breakloop; } else { throw new NoViableAltForCharException(cached_LA1, getFilename(), getLine(), getColumn());; }
|
||||
}
|
||||
|
||||
_cnt178++;
|
||||
_cnt176++;
|
||||
}
|
||||
_loop178_breakloop: ;
|
||||
_loop176_breakloop: ;
|
||||
} // ( ... )+
|
||||
match('.');
|
||||
mDECIMAL_DIGIT(false);
|
||||
@@ -1241,13 +1239,31 @@ _loop178_breakloop: ;
|
||||
}
|
||||
catch (RecognitionException)
|
||||
{
|
||||
synPredMatched179 = false;
|
||||
synPredMatched177 = false;
|
||||
}
|
||||
rewind(_m179);
|
||||
rewind(_m177);
|
||||
inputState.guessing--;
|
||||
}
|
||||
if ( synPredMatched179 )
|
||||
if ( synPredMatched177 )
|
||||
{
|
||||
{ // ( ... )+
|
||||
int _cnt179=0;
|
||||
for (;;)
|
||||
{
|
||||
if (((cached_LA1 >= '0' && cached_LA1 <= '9')))
|
||||
{
|
||||
mDECIMAL_DIGIT(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_cnt179 >= 1) { goto _loop179_breakloop; } else { throw new NoViableAltForCharException(cached_LA1, getFilename(), getLine(), getColumn());; }
|
||||
}
|
||||
|
||||
_cnt179++;
|
||||
}
|
||||
_loop179_breakloop: ;
|
||||
} // ( ... )+
|
||||
match('.');
|
||||
{ // ( ... )+
|
||||
int _cnt181=0;
|
||||
for (;;)
|
||||
@@ -1264,24 +1280,6 @@ _loop178_breakloop: ;
|
||||
_cnt181++;
|
||||
}
|
||||
_loop181_breakloop: ;
|
||||
} // ( ... )+
|
||||
match('.');
|
||||
{ // ( ... )+
|
||||
int _cnt183=0;
|
||||
for (;;)
|
||||
{
|
||||
if (((cached_LA1 >= '0' && cached_LA1 <= '9')))
|
||||
{
|
||||
mDECIMAL_DIGIT(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_cnt183 >= 1) { goto _loop183_breakloop; } else { throw new NoViableAltForCharException(cached_LA1, getFilename(), getLine(), getColumn());; }
|
||||
}
|
||||
|
||||
_cnt183++;
|
||||
}
|
||||
_loop183_breakloop: ;
|
||||
} // ( ... )+
|
||||
{
|
||||
if ((cached_LA1=='E'||cached_LA1=='e'))
|
||||
@@ -1307,16 +1305,16 @@ _loop183_breakloop: ;
|
||||
}
|
||||
}
|
||||
else {
|
||||
bool synPredMatched190 = false;
|
||||
bool synPredMatched188 = false;
|
||||
if ((((cached_LA1 >= '0' && cached_LA1 <= '9')) && (tokenSet_4_.member(cached_LA2))))
|
||||
{
|
||||
int _m190 = mark();
|
||||
synPredMatched190 = true;
|
||||
int _m188 = mark();
|
||||
synPredMatched188 = true;
|
||||
inputState.guessing++;
|
||||
try {
|
||||
{
|
||||
{ // ( ... )+
|
||||
int _cnt188=0;
|
||||
int _cnt186=0;
|
||||
for (;;)
|
||||
{
|
||||
if (((cached_LA1 >= '0' && cached_LA1 <= '9')))
|
||||
@@ -1325,12 +1323,12 @@ _loop183_breakloop: ;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_cnt188 >= 1) { goto _loop188_breakloop; } else { throw new NoViableAltForCharException(cached_LA1, getFilename(), getLine(), getColumn());; }
|
||||
if (_cnt186 >= 1) { goto _loop186_breakloop; } else { throw new NoViableAltForCharException(cached_LA1, getFilename(), getLine(), getColumn());; }
|
||||
}
|
||||
|
||||
_cnt188++;
|
||||
_cnt186++;
|
||||
}
|
||||
_loop188_breakloop: ;
|
||||
_loop186_breakloop: ;
|
||||
} // ( ... )+
|
||||
{
|
||||
mEXPONENT_PART(false);
|
||||
@@ -1339,15 +1337,15 @@ _loop188_breakloop: ;
|
||||
}
|
||||
catch (RecognitionException)
|
||||
{
|
||||
synPredMatched190 = false;
|
||||
synPredMatched188 = false;
|
||||
}
|
||||
rewind(_m190);
|
||||
rewind(_m188);
|
||||
inputState.guessing--;
|
||||
}
|
||||
if ( synPredMatched190 )
|
||||
if ( synPredMatched188 )
|
||||
{
|
||||
{ // ( ... )+
|
||||
int _cnt192=0;
|
||||
int _cnt190=0;
|
||||
for (;;)
|
||||
{
|
||||
if (((cached_LA1 >= '0' && cached_LA1 <= '9')))
|
||||
@@ -1356,12 +1354,12 @@ _loop188_breakloop: ;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_cnt192 >= 1) { goto _loop192_breakloop; } else { throw new NoViableAltForCharException(cached_LA1, getFilename(), getLine(), getColumn());; }
|
||||
if (_cnt190 >= 1) { goto _loop190_breakloop; } else { throw new NoViableAltForCharException(cached_LA1, getFilename(), getLine(), getColumn());; }
|
||||
}
|
||||
|
||||
_cnt192++;
|
||||
_cnt190++;
|
||||
}
|
||||
_loop192_breakloop: ;
|
||||
_loop190_breakloop: ;
|
||||
} // ( ... )+
|
||||
{
|
||||
mEXPONENT_PART(false);
|
||||
@@ -1381,16 +1379,16 @@ _loop192_breakloop: ;
|
||||
}
|
||||
}
|
||||
else {
|
||||
bool synPredMatched199 = false;
|
||||
bool synPredMatched197 = false;
|
||||
if ((((cached_LA1 >= '0' && cached_LA1 <= '9')) && (tokenSet_5_.member(cached_LA2))))
|
||||
{
|
||||
int _m199 = mark();
|
||||
synPredMatched199 = true;
|
||||
int _m197 = mark();
|
||||
synPredMatched197 = true;
|
||||
inputState.guessing++;
|
||||
try {
|
||||
{
|
||||
{ // ( ... )+
|
||||
int _cnt197=0;
|
||||
int _cnt195=0;
|
||||
for (;;)
|
||||
{
|
||||
if (((cached_LA1 >= '0' && cached_LA1 <= '9')))
|
||||
@@ -1399,12 +1397,12 @@ _loop192_breakloop: ;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_cnt197 >= 1) { goto _loop197_breakloop; } else { throw new NoViableAltForCharException(cached_LA1, getFilename(), getLine(), getColumn());; }
|
||||
if (_cnt195 >= 1) { goto _loop195_breakloop; } else { throw new NoViableAltForCharException(cached_LA1, getFilename(), getLine(), getColumn());; }
|
||||
}
|
||||
|
||||
_cnt197++;
|
||||
_cnt195++;
|
||||
}
|
||||
_loop197_breakloop: ;
|
||||
_loop195_breakloop: ;
|
||||
} // ( ... )+
|
||||
{
|
||||
mREAL_TYPE_SUFFIX(false);
|
||||
@@ -1413,15 +1411,15 @@ _loop197_breakloop: ;
|
||||
}
|
||||
catch (RecognitionException)
|
||||
{
|
||||
synPredMatched199 = false;
|
||||
synPredMatched197 = false;
|
||||
}
|
||||
rewind(_m199);
|
||||
rewind(_m197);
|
||||
inputState.guessing--;
|
||||
}
|
||||
if ( synPredMatched199 )
|
||||
if ( synPredMatched197 )
|
||||
{
|
||||
{ // ( ... )+
|
||||
int _cnt201=0;
|
||||
int _cnt199=0;
|
||||
for (;;)
|
||||
{
|
||||
if (((cached_LA1 >= '0' && cached_LA1 <= '9')))
|
||||
@@ -1430,12 +1428,12 @@ _loop197_breakloop: ;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_cnt201 >= 1) { goto _loop201_breakloop; } else { throw new NoViableAltForCharException(cached_LA1, getFilename(), getLine(), getColumn());; }
|
||||
if (_cnt199 >= 1) { goto _loop199_breakloop; } else { throw new NoViableAltForCharException(cached_LA1, getFilename(), getLine(), getColumn());; }
|
||||
}
|
||||
|
||||
_cnt201++;
|
||||
_cnt199++;
|
||||
}
|
||||
_loop201_breakloop: ;
|
||||
_loop199_breakloop: ;
|
||||
} // ( ... )+
|
||||
{
|
||||
mREAL_TYPE_SUFFIX(false);
|
||||
@@ -1447,7 +1445,7 @@ _loop201_breakloop: ;
|
||||
}
|
||||
else if (((cached_LA1 >= '0' && cached_LA1 <= '9')) && (true)) {
|
||||
{ // ( ... )+
|
||||
int _cnt204=0;
|
||||
int _cnt202=0;
|
||||
for (;;)
|
||||
{
|
||||
if (((cached_LA1 >= '0' && cached_LA1 <= '9')))
|
||||
@@ -1456,12 +1454,12 @@ _loop201_breakloop: ;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_cnt204 >= 1) { goto _loop204_breakloop; } else { throw new NoViableAltForCharException(cached_LA1, getFilename(), getLine(), getColumn());; }
|
||||
if (_cnt202 >= 1) { goto _loop202_breakloop; } else { throw new NoViableAltForCharException(cached_LA1, getFilename(), getLine(), getColumn());; }
|
||||
}
|
||||
|
||||
_cnt204++;
|
||||
_cnt202++;
|
||||
}
|
||||
_loop204_breakloop: ;
|
||||
_loop202_breakloop: ;
|
||||
} // ( ... )+
|
||||
{
|
||||
if ((tokenSet_6_.member(cached_LA1)))
|
||||
@@ -1530,14 +1528,14 @@ _loop204_breakloop: ;
|
||||
}
|
||||
else
|
||||
{
|
||||
goto _loop216_breakloop;
|
||||
goto _loop214_breakloop;
|
||||
}
|
||||
|
||||
}
|
||||
_loop216_breakloop: ;
|
||||
_loop214_breakloop: ;
|
||||
} // ( ... )*
|
||||
{ // ( ... )+
|
||||
int _cnt218=0;
|
||||
int _cnt216=0;
|
||||
for (;;)
|
||||
{
|
||||
if (((cached_LA1 >= '0' && cached_LA1 <= '9')))
|
||||
@@ -1546,12 +1544,12 @@ _loop216_breakloop: ;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_cnt218 >= 1) { goto _loop218_breakloop; } else { throw new NoViableAltForCharException(cached_LA1, getFilename(), getLine(), getColumn());; }
|
||||
if (_cnt216 >= 1) { goto _loop216_breakloop; } else { throw new NoViableAltForCharException(cached_LA1, getFilename(), getLine(), getColumn());; }
|
||||
}
|
||||
|
||||
_cnt218++;
|
||||
_cnt216++;
|
||||
}
|
||||
_loop218_breakloop: ;
|
||||
_loop216_breakloop: ;
|
||||
} // ( ... )+
|
||||
break;
|
||||
}
|
||||
@@ -1567,14 +1565,14 @@ _loop218_breakloop: ;
|
||||
}
|
||||
else
|
||||
{
|
||||
goto _loop220_breakloop;
|
||||
goto _loop218_breakloop;
|
||||
}
|
||||
|
||||
}
|
||||
_loop220_breakloop: ;
|
||||
_loop218_breakloop: ;
|
||||
} // ( ... )*
|
||||
{ // ( ... )+
|
||||
int _cnt222=0;
|
||||
int _cnt220=0;
|
||||
for (;;)
|
||||
{
|
||||
if (((cached_LA1 >= '0' && cached_LA1 <= '9')))
|
||||
@@ -1583,12 +1581,12 @@ _loop220_breakloop: ;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_cnt222 >= 1) { goto _loop222_breakloop; } else { throw new NoViableAltForCharException(cached_LA1, getFilename(), getLine(), getColumn());; }
|
||||
if (_cnt220 >= 1) { goto _loop220_breakloop; } else { throw new NoViableAltForCharException(cached_LA1, getFilename(), getLine(), getColumn());; }
|
||||
}
|
||||
|
||||
_cnt222++;
|
||||
_cnt220++;
|
||||
}
|
||||
_loop222_breakloop: ;
|
||||
_loop220_breakloop: ;
|
||||
} // ( ... )+
|
||||
break;
|
||||
}
|
||||
@@ -1719,7 +1717,7 @@ _loop222_breakloop: ;
|
||||
|
||||
match("0x");
|
||||
{ // ( ... )+
|
||||
int _cnt208=0;
|
||||
int _cnt206=0;
|
||||
for (;;)
|
||||
{
|
||||
if ((tokenSet_7_.member(cached_LA1)))
|
||||
@@ -1728,12 +1726,12 @@ _loop222_breakloop: ;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_cnt208 >= 1) { goto _loop208_breakloop; } else { throw new NoViableAltForCharException(cached_LA1, getFilename(), getLine(), getColumn());; }
|
||||
if (_cnt206 >= 1) { goto _loop206_breakloop; } else { throw new NoViableAltForCharException(cached_LA1, getFilename(), getLine(), getColumn());; }
|
||||
}
|
||||
|
||||
_cnt208++;
|
||||
_cnt206++;
|
||||
}
|
||||
_loop208_breakloop: ;
|
||||
_loop206_breakloop: ;
|
||||
} // ( ... )+
|
||||
{
|
||||
if ((tokenSet_6_.member(cached_LA1)))
|
||||
|
||||
@@ -78,25 +78,24 @@ namespace Spring.Expressions.Parser
|
||||
public const int INTEGER_LITERAL = 51;
|
||||
public const int HEXADECIMAL_INTEGER_LITERAL = 52;
|
||||
public const int REAL_LITERAL = 53;
|
||||
public const int LITERAL_date = 54;
|
||||
public const int EQUAL = 55;
|
||||
public const int NOT_EQUAL = 56;
|
||||
public const int LESS_THAN = 57;
|
||||
public const int LESS_THAN_OR_EQUAL = 58;
|
||||
public const int GREATER_THAN = 59;
|
||||
public const int GREATER_THAN_OR_EQUAL = 60;
|
||||
public const int WS = 61;
|
||||
public const int BACKTICK = 62;
|
||||
public const int BACKSLASH = 63;
|
||||
public const int DOT_ESCAPED = 64;
|
||||
public const int APOS = 65;
|
||||
public const int NUMERIC_LITERAL = 66;
|
||||
public const int DECIMAL_DIGIT = 67;
|
||||
public const int INTEGER_TYPE_SUFFIX = 68;
|
||||
public const int HEX_DIGIT = 69;
|
||||
public const int EXPONENT_PART = 70;
|
||||
public const int SIGN = 71;
|
||||
public const int REAL_TYPE_SUFFIX = 72;
|
||||
public const int EQUAL = 54;
|
||||
public const int NOT_EQUAL = 55;
|
||||
public const int LESS_THAN = 56;
|
||||
public const int LESS_THAN_OR_EQUAL = 57;
|
||||
public const int GREATER_THAN = 58;
|
||||
public const int GREATER_THAN_OR_EQUAL = 59;
|
||||
public const int WS = 60;
|
||||
public const int BACKTICK = 61;
|
||||
public const int BACKSLASH = 62;
|
||||
public const int DOT_ESCAPED = 63;
|
||||
public const int APOS = 64;
|
||||
public const int NUMERIC_LITERAL = 65;
|
||||
public const int DECIMAL_DIGIT = 66;
|
||||
public const int INTEGER_TYPE_SUFFIX = 67;
|
||||
public const int HEX_DIGIT = 68;
|
||||
public const int EXPONENT_PART = 69;
|
||||
public const int SIGN = 70;
|
||||
public const int REAL_TYPE_SUFFIX = 71;
|
||||
|
||||
|
||||
// CLOVER:OFF
|
||||
@@ -1190,7 +1189,6 @@ _loop29_breakloop: ;
|
||||
case INTEGER_LITERAL:
|
||||
case HEXADECIMAL_INTEGER_LITERAL:
|
||||
case REAL_LITERAL:
|
||||
case LITERAL_date:
|
||||
{
|
||||
literal();
|
||||
if (0 == inputState.guessing)
|
||||
@@ -1892,16 +1890,6 @@ _loop67_breakloop: ;
|
||||
literal_AST = (Spring.Expressions.SpringAST)currentAST.root;
|
||||
break;
|
||||
}
|
||||
case LITERAL_date:
|
||||
{
|
||||
dateLiteral();
|
||||
if (0 == inputState.guessing)
|
||||
{
|
||||
astFactory.addASTChild(ref currentAST, (AST)returnAST);
|
||||
}
|
||||
literal_AST = (Spring.Expressions.SpringAST)currentAST.root;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
throw new NoViableAltException(LT(1), getFilename());
|
||||
@@ -3261,58 +3249,6 @@ _loop96_breakloop: ;
|
||||
returnAST = boolLiteral_AST;
|
||||
}
|
||||
|
||||
public void dateLiteral() //throws RecognitionException, TokenStreamException
|
||||
{
|
||||
|
||||
returnAST = null;
|
||||
ASTPair currentAST = new ASTPair();
|
||||
Spring.Expressions.SpringAST dateLiteral_AST = null;
|
||||
|
||||
try { // for error handling
|
||||
Spring.Expressions.DateLiteralNode tmp112_AST = null;
|
||||
tmp112_AST = (Spring.Expressions.DateLiteralNode) astFactory.create(LT(1), "Spring.Expressions.DateLiteralNode");
|
||||
astFactory.makeASTRoot(ref currentAST, (AST)tmp112_AST);
|
||||
match(LITERAL_date);
|
||||
match(LPAREN);
|
||||
Spring.Expressions.SpringAST tmp114_AST = null;
|
||||
tmp114_AST = (Spring.Expressions.SpringAST) astFactory.create(LT(1));
|
||||
astFactory.addASTChild(ref currentAST, (AST)tmp114_AST);
|
||||
match(STRING_LITERAL);
|
||||
{
|
||||
if ((LA(1)==COMMA))
|
||||
{
|
||||
match(COMMA);
|
||||
Spring.Expressions.SpringAST tmp116_AST = null;
|
||||
tmp116_AST = (Spring.Expressions.SpringAST) astFactory.create(LT(1));
|
||||
astFactory.addASTChild(ref currentAST, (AST)tmp116_AST);
|
||||
match(STRING_LITERAL);
|
||||
}
|
||||
else if ((LA(1)==RPAREN)) {
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NoViableAltException(LT(1), getFilename());
|
||||
}
|
||||
|
||||
}
|
||||
match(RPAREN);
|
||||
dateLiteral_AST = (Spring.Expressions.SpringAST)currentAST.root;
|
||||
}
|
||||
catch (RecognitionException ex)
|
||||
{
|
||||
if (0 == inputState.guessing)
|
||||
{
|
||||
reportError(ex);
|
||||
recover(ex,tokenSet_2_);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
returnAST = dateLiteral_AST;
|
||||
}
|
||||
|
||||
public new Spring.Expressions.SpringAST getAST()
|
||||
{
|
||||
return (Spring.Expressions.SpringAST) returnAST;
|
||||
@@ -3328,7 +3264,7 @@ _loop96_breakloop: ;
|
||||
}
|
||||
static public void initializeASTFactory( ASTFactory factory )
|
||||
{
|
||||
factory.setMaxNodeType(72);
|
||||
factory.setMaxNodeType(71);
|
||||
}
|
||||
|
||||
public static readonly string[] tokenNames_ = new string[] {
|
||||
@@ -3386,7 +3322,6 @@ _loop96_breakloop: ;
|
||||
@"""INTEGER_LITERAL""",
|
||||
@"""HEXADECIMAL_INTEGER_LITERAL""",
|
||||
@"""REAL_LITERAL""",
|
||||
@"""date""",
|
||||
@"""EQUAL""",
|
||||
@"""NOT_EQUAL""",
|
||||
@"""LESS_THAN""",
|
||||
@@ -3421,7 +3356,7 @@ _loop96_breakloop: ;
|
||||
public static readonly BitSet tokenSet_1_ = new BitSet(mk_tokenSet_1_());
|
||||
private static long[] mk_tokenSet_2_()
|
||||
{
|
||||
long[] data = { 2269831713112653570L, 0L};
|
||||
long[] data = { 1134924607015288578L, 0L};
|
||||
return data;
|
||||
}
|
||||
public static readonly BitSet tokenSet_2_ = new BitSet(mk_tokenSet_2_());
|
||||
@@ -3445,7 +3380,7 @@ _loop96_breakloop: ;
|
||||
public static readonly BitSet tokenSet_5_ = new BitSet(mk_tokenSet_5_());
|
||||
private static long[] mk_tokenSet_6_()
|
||||
{
|
||||
long[] data = { 2269814212194793472L, 0L};
|
||||
long[] data = { 1134907106097428480L, 0L};
|
||||
return data;
|
||||
}
|
||||
public static readonly BitSet tokenSet_6_ = new BitSet(mk_tokenSet_6_());
|
||||
@@ -3457,37 +3392,37 @@ _loop96_breakloop: ;
|
||||
public static readonly BitSet tokenSet_7_ = new BitSet(mk_tokenSet_7_());
|
||||
private static long[] mk_tokenSet_8_()
|
||||
{
|
||||
long[] data = { 2269815620960583426L, 0L};
|
||||
long[] data = { 1134908514863218434L, 0L};
|
||||
return data;
|
||||
}
|
||||
public static readonly BitSet tokenSet_8_ = new BitSet(mk_tokenSet_8_());
|
||||
private static long[] mk_tokenSet_9_()
|
||||
{
|
||||
long[] data = { 35710725750194368L, 0L};
|
||||
long[] data = { 17696327240712384L, 0L};
|
||||
return data;
|
||||
}
|
||||
public static readonly BitSet tokenSet_9_ = new BitSet(mk_tokenSet_9_());
|
||||
private static long[] mk_tokenSet_10_()
|
||||
{
|
||||
long[] data = { 2269815621010915074L, 0L};
|
||||
long[] data = { 1134908514913550082L, 0L};
|
||||
return data;
|
||||
}
|
||||
public static readonly BitSet tokenSet_10_ = new BitSet(mk_tokenSet_10_());
|
||||
private static long[] mk_tokenSet_11_()
|
||||
{
|
||||
long[] data = { 2269815621480677122L, 0L};
|
||||
long[] data = { 1134908515383312130L, 0L};
|
||||
return data;
|
||||
}
|
||||
public static readonly BitSet tokenSet_11_ = new BitSet(mk_tokenSet_11_());
|
||||
private static long[] mk_tokenSet_12_()
|
||||
{
|
||||
long[] data = { 35710724626120896L, 0L};
|
||||
long[] data = { 17696326116638912L, 0L};
|
||||
return data;
|
||||
}
|
||||
public static readonly BitSet tokenSet_12_ = new BitSet(mk_tokenSet_12_());
|
||||
private static long[] mk_tokenSet_13_()
|
||||
{
|
||||
long[] data = { 2269815622017548034L, 0L};
|
||||
long[] data = { 1134908515920183042L, 0L};
|
||||
return data;
|
||||
}
|
||||
public static readonly BitSet tokenSet_13_ = new BitSet(mk_tokenSet_13_());
|
||||
@@ -3511,7 +3446,7 @@ _loop96_breakloop: ;
|
||||
public static readonly BitSet tokenSet_16_ = new BitSet(mk_tokenSet_16_());
|
||||
private static long[] mk_tokenSet_17_()
|
||||
{
|
||||
long[] data = { -35184381001744L, 511L, 0L, 0L};
|
||||
long[] data = { -35184381001744L, 255L, 0L, 0L};
|
||||
return data;
|
||||
}
|
||||
public static readonly BitSet tokenSet_17_ = new BitSet(mk_tokenSet_17_());
|
||||
@@ -3529,7 +3464,7 @@ _loop96_breakloop: ;
|
||||
public static readonly BitSet tokenSet_19_ = new BitSet(mk_tokenSet_19_());
|
||||
private static long[] mk_tokenSet_20_()
|
||||
{
|
||||
long[] data = { 2270957613019496194L, 0L};
|
||||
long[] data = { 1136050506922131202L, 0L};
|
||||
return data;
|
||||
}
|
||||
public static readonly BitSet tokenSet_20_ = new BitSet(mk_tokenSet_20_());
|
||||
@@ -3541,7 +3476,7 @@ _loop96_breakloop: ;
|
||||
public static readonly BitSet tokenSet_21_ = new BitSet(mk_tokenSet_21_());
|
||||
private static long[] mk_tokenSet_22_()
|
||||
{
|
||||
long[] data = { 2305806450443419584L, 0L};
|
||||
long[] data = { 1152884945836572608L, 0L};
|
||||
return data;
|
||||
}
|
||||
public static readonly BitSet tokenSet_22_ = new BitSet(mk_tokenSet_22_());
|
||||
|
||||
@@ -56,25 +56,24 @@ namespace Spring.Expressions.Parser
|
||||
public const int INTEGER_LITERAL = 51;
|
||||
public const int HEXADECIMAL_INTEGER_LITERAL = 52;
|
||||
public const int REAL_LITERAL = 53;
|
||||
public const int LITERAL_date = 54;
|
||||
public const int EQUAL = 55;
|
||||
public const int NOT_EQUAL = 56;
|
||||
public const int LESS_THAN = 57;
|
||||
public const int LESS_THAN_OR_EQUAL = 58;
|
||||
public const int GREATER_THAN = 59;
|
||||
public const int GREATER_THAN_OR_EQUAL = 60;
|
||||
public const int WS = 61;
|
||||
public const int BACKTICK = 62;
|
||||
public const int BACKSLASH = 63;
|
||||
public const int DOT_ESCAPED = 64;
|
||||
public const int APOS = 65;
|
||||
public const int NUMERIC_LITERAL = 66;
|
||||
public const int DECIMAL_DIGIT = 67;
|
||||
public const int INTEGER_TYPE_SUFFIX = 68;
|
||||
public const int HEX_DIGIT = 69;
|
||||
public const int EXPONENT_PART = 70;
|
||||
public const int SIGN = 71;
|
||||
public const int REAL_TYPE_SUFFIX = 72;
|
||||
public const int EQUAL = 54;
|
||||
public const int NOT_EQUAL = 55;
|
||||
public const int LESS_THAN = 56;
|
||||
public const int LESS_THAN_OR_EQUAL = 57;
|
||||
public const int GREATER_THAN = 58;
|
||||
public const int GREATER_THAN_OR_EQUAL = 59;
|
||||
public const int WS = 60;
|
||||
public const int BACKTICK = 61;
|
||||
public const int BACKSLASH = 62;
|
||||
public const int DOT_ESCAPED = 63;
|
||||
public const int APOS = 64;
|
||||
public const int NUMERIC_LITERAL = 65;
|
||||
public const int DECIMAL_DIGIT = 66;
|
||||
public const int INTEGER_TYPE_SUFFIX = 67;
|
||||
public const int HEX_DIGIT = 68;
|
||||
public const int EXPONENT_PART = 69;
|
||||
public const int SIGN = 70;
|
||||
public const int REAL_TYPE_SUFFIX = 71;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,22 +50,21 @@ LCURLY=50
|
||||
INTEGER_LITERAL=51
|
||||
HEXADECIMAL_INTEGER_LITERAL=52
|
||||
REAL_LITERAL=53
|
||||
LITERAL_date="date"=54
|
||||
EQUAL=55
|
||||
NOT_EQUAL=56
|
||||
LESS_THAN=57
|
||||
LESS_THAN_OR_EQUAL=58
|
||||
GREATER_THAN=59
|
||||
GREATER_THAN_OR_EQUAL=60
|
||||
WS=61
|
||||
BACKTICK=62
|
||||
BACKSLASH=63
|
||||
DOT_ESCAPED=64
|
||||
APOS=65
|
||||
NUMERIC_LITERAL=66
|
||||
DECIMAL_DIGIT=67
|
||||
INTEGER_TYPE_SUFFIX=68
|
||||
HEX_DIGIT=69
|
||||
EXPONENT_PART=70
|
||||
SIGN=71
|
||||
REAL_TYPE_SUFFIX=72
|
||||
EQUAL=54
|
||||
NOT_EQUAL=55
|
||||
LESS_THAN=56
|
||||
LESS_THAN_OR_EQUAL=57
|
||||
GREATER_THAN=58
|
||||
GREATER_THAN_OR_EQUAL=59
|
||||
WS=60
|
||||
BACKTICK=61
|
||||
BACKSLASH=62
|
||||
DOT_ESCAPED=63
|
||||
APOS=64
|
||||
NUMERIC_LITERAL=65
|
||||
DECIMAL_DIGIT=66
|
||||
INTEGER_TYPE_SUFFIX=67
|
||||
HEX_DIGIT=68
|
||||
EXPONENT_PART=69
|
||||
SIGN=70
|
||||
REAL_TYPE_SUFFIX=71
|
||||
|
||||
@@ -57,7 +57,7 @@ namespace Spring.Expressions.Processors
|
||||
Type targetType = typeof(double);
|
||||
if (args == null || args.Length == 0)
|
||||
{
|
||||
throw new ArgumentNullException("convert() processor requires a Type value argument.");
|
||||
throw new ArgumentNullException("args", "convert() processor requires a Type value argument.");
|
||||
}
|
||||
else if (args.Length == 1)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Spring.Expressions.Processors
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts a string literal to a <see cref="DateTime"/> instance.
|
||||
/// </summary>
|
||||
/// <author>Erich Eichinger</author>
|
||||
public class DateConversionProcessor : IMethodCallProcessor
|
||||
{
|
||||
public object Process(object context, object[] args)
|
||||
{
|
||||
int argc = args != null ? args.Length : 0;
|
||||
switch (argc)
|
||||
{
|
||||
case 1:
|
||||
return DateTime.Parse((string)args[0]);
|
||||
case 2:
|
||||
return DateTime.ParseExact((string)args[0], (string)args[1], CultureInfo.InvariantCulture);
|
||||
default:
|
||||
throw new ArgumentException("date(<date> [,<format>]) expects 1 or 2 arguments");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
|
||||
namespace Spring.Expressions.Processors
|
||||
{
|
||||
/// <summary>
|
||||
/// </summary>
|
||||
/// <author>Erich Eichinger</author>
|
||||
public interface IMethodCallProcessor
|
||||
{
|
||||
object Process(object context, object[] args);
|
||||
}
|
||||
}
|
||||
@@ -461,6 +461,8 @@
|
||||
<Compile Include="Expressions\Parser\antlr\TokenWithIndex.cs" />
|
||||
<Compile Include="Expressions\Parser\antlr\TreeParser.cs" />
|
||||
<Compile Include="Expressions\Parser\antlr\TreeParserSharedInputState.cs" />
|
||||
<Compile Include="Expressions\Processors\DateConversionProcessor.cs" />
|
||||
<Compile Include="Expressions\Processors\IMethodCallProcessor.cs" />
|
||||
<Compile Include="Expressions\SyntaxErrorException.cs" />
|
||||
<Compile Include="Expressions\Parser\ExpressionLexer.cs" />
|
||||
<Compile Include="Expressions\Parser\ExpressionParser.cs" />
|
||||
@@ -512,9 +514,6 @@
|
||||
<Compile Include="Expressions\OpIn.cs" />
|
||||
<Compile Include="Expressions\QualifiedIdentifier.cs" />
|
||||
<Compile Include="Expressions\NamedArgumentNode.cs" />
|
||||
<Compile Include="Expressions\DateLiteralNode.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Expressions\Expression.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
|
||||
@@ -293,8 +293,17 @@ namespace Spring.Expressions
|
||||
Assert.AreEqual("date", dateLiteral);
|
||||
}
|
||||
|
||||
[Test(Description = "http://jira.springframework.org/browse/SPRNET-1155")]
|
||||
[Test(Description = "http://jira.springframework.org/browse/SPRNET-944")]
|
||||
public void TestDateVariableExpression()
|
||||
{
|
||||
Hashtable vars = new Hashtable();
|
||||
vars["date"] = "2008-05-15";
|
||||
object value = ExpressionEvaluator.GetValue(null, "#date", vars);
|
||||
Assert.That(value, Is.EqualTo("2008-05-15"));
|
||||
}
|
||||
|
||||
[Test(Description = "http://jira.springframework.org/browse/SPRNET-1155")]
|
||||
public void TestDateVariableExpressionCamelCased()
|
||||
{
|
||||
Hashtable vars = new Hashtable();
|
||||
vars["Date"] = "2008-05-15";
|
||||
@@ -466,17 +475,14 @@ namespace Spring.Expressions
|
||||
public void TestDateLiterals()
|
||||
{
|
||||
IExpression exp = Expression.Parse("date('1974/08/24')");
|
||||
Assert.AreEqual(exp.GetValue(), new DateTime(1974, 8, 24));
|
||||
Assert.AreEqual(exp.GetValue(), new DateTime(1974, 8, 24));
|
||||
Assert.AreEqual(ExpressionEvaluator.GetValue(null, "date('1974-08-24')"), new DateTime(1974, 8, 24));
|
||||
Assert.AreEqual(ExpressionEvaluator.GetValue(null, "date('08-24-1974', 'MM-dd-yyyy')"),
|
||||
new DateTime(1974, 8, 24));
|
||||
Assert.AreEqual(ExpressionEvaluator.GetValue(null, "date('08/24/1974', 'MM/dd/yyyy')"),
|
||||
new DateTime(1974, 8, 24));
|
||||
Assert.AreEqual(ExpressionEvaluator.GetValue(null, "date('1974-08-24 12:35:06Z', 'u')"),
|
||||
new DateTime(1974, 8, 24, 12, 35, 6));
|
||||
Assert.AreEqual(ExpressionEvaluator.GetValue(null, "date('1974/08/24').Year"), 1974);
|
||||
Assert.AreEqual(ExpressionEvaluator.GetValue(null, "date('1974/08/24').AddYears(31).Year"), 2005);
|
||||
Assert.AreEqual(new DateTime(1974, 8, 24), exp.GetValue());
|
||||
Assert.AreEqual(new DateTime(1974, 8, 24), exp.GetValue());
|
||||
Assert.AreEqual(new DateTime(1974, 8, 24), ExpressionEvaluator.GetValue(null, "date('1974-08-24')"));
|
||||
Assert.AreEqual(new DateTime(1974, 8, 24), ExpressionEvaluator.GetValue(null, "date('08-24-1974', 'MM-dd-yyyy')"));
|
||||
Assert.AreEqual(new DateTime(1974, 8, 24), ExpressionEvaluator.GetValue(null, "date('08/24/1974', 'MM/dd/yyyy')"));
|
||||
Assert.AreEqual(new DateTime(1974, 8, 24, 12, 35, 6), ExpressionEvaluator.GetValue(null, "date('1974-08-24 12:35:06Z', 'u')"));
|
||||
Assert.AreEqual(1974, ExpressionEvaluator.GetValue(null, "date('1974/08/24').Year"));
|
||||
Assert.AreEqual(2005, ExpressionEvaluator.GetValue(null, "date('1974/08/24').AddYears(31).Year"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user