#region MIT license // // MIT license // // Copyright (c) 2007-2008 Jiri Moudry, Pascal Craponne // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // #endregion using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using DbLinq.Data.Linq.Sugar; using DbLinq.Data.Linq.Sugar.ExpressionMutator; using DbLinq.Data.Linq.Sugar.Expressions; namespace DbLinq.Data.Linq.Sugar.Implementation { internal class SpecialExpressionTranslator : ISpecialExpressionTranslator { /// /// Translate a hierarchy's SpecialExpressions to Expressions /// /// /// public Expression Translate(Expression expression) { return expression.Recurse(Analyzer); } protected virtual Expression Analyzer(Expression expression) { if (expression is SpecialExpression) return Translate((SpecialExpression)expression); else if (expression is StartIndexOffsetExpression) return Translate(((StartIndexOffsetExpression)expression).InnerExpression); return expression; } /// /// Translates a SpecialExpression to standard Expression equivalent /// /// /// protected virtual Expression Translate(SpecialExpression specialExpression) { var operands = specialExpression.Operands.ToList(); switch (specialExpression.SpecialNodeType) // SETuse { case SpecialExpressionType.IsNull: return TranslateIsNull(operands); case SpecialExpressionType.IsNotNull: return TranslateIsNotNull(operands); case SpecialExpressionType.Concat: return TranslateConcat(operands); //case SpecialExpressionType.Count: // break; //case SpecialExpressionType.Like: // break; //case SpecialExpressionType.Min: // break; //case SpecialExpressionType.Max: // break; //case SpecialExpressionType.Sum: // break; //case SpecialExpressionType.Average: // break; case SpecialExpressionType.StringLength: return TranslateStringLength(operands); case SpecialExpressionType.ToUpper: return GetStandardCallInvoke("ToUpper", operands); case SpecialExpressionType.ToLower: return GetStandardCallInvoke("ToLower", operands); //case SpecialExpressionType.In: // break; case SpecialExpressionType.StringInsert: return GetStandardCallInvoke("Insert", operands); case SpecialExpressionType.Substring: case SpecialExpressionType.Trim: case SpecialExpressionType.LTrim: case SpecialExpressionType.RTrim: case SpecialExpressionType.Replace: case SpecialExpressionType.Remove: case SpecialExpressionType.IndexOf: case SpecialExpressionType.Year: case SpecialExpressionType.Month: case SpecialExpressionType.Day: case SpecialExpressionType.Hour: case SpecialExpressionType.Minute: case SpecialExpressionType.Millisecond: case SpecialExpressionType.Date: return GetStandardCallInvoke(specialExpression.SpecialNodeType.ToString(), operands); case SpecialExpressionType.Now: return GetDateTimeNowCall(operands); case SpecialExpressionType.DateDiffInMilliseconds: return GetCallDateDiffInMilliseconds(operands); default: throw Error.BadArgument("S0078: Implement translator for {0}", specialExpression.SpecialNodeType); } } private Expression GetCallDateDiffInMilliseconds(List operands) { return Expression.MakeMemberAccess(Expression.Subtract(operands.First(), operands.ElementAt(1)), typeof(TimeSpan).GetProperty("TotalMilliseconds")); } private Expression GetDateTimeNowCall(List operands) { return Expression.Call(typeof(DateTime).GetProperty("Now").GetGetMethod()); } private Expression TranslateStringLength(List operands) { return Expression.MakeMemberAccess(operands[0], typeof(string).GetProperty("Length")); } protected virtual Expression GetStandardCallInvoke(string methodName, List operands) { var parametersExpressions = operands.Skip(1); return Expression.Call(operands[0], operands[0].Type.GetMethod(methodName, parametersExpressions.Select(op => op.Type).ToArray()), parametersExpressions); } //protected virtual Expression TranslateRemove(List operands) //{ // if (operands.Count > 2) // { // return Expression.Call(operands[0], // typeof(string).GetMethod("Remove", new[] { typeof(int), typeof(int) }), // operands[1], operands[2]); // } // return Expression.Call(operands[0], // typeof(string).GetMethod("Remove", new[] { typeof(int) }), // operands[1]); //} //protected virtual Expression TranslateStringIndexOf(List operands) //{ // if (operands.Count == 2 && operands[1].Type == typeof(string)) // { // return Expression.Call(operands[0], // typeof(string).GetMethod("IndexOf", new[] { typeof(string)}), // operands[1]); // } // throw new NotSupportedException(); //} //protected virtual Expression TranslateReplace(List operands) //{ // if (operands.ElementAt(1).Type == typeof(string)) // { // return Expression.Call(operands[0], // typeof(string).GetMethod("Replace", new[] { typeof(string), typeof(string) }), // operands[1], operands[2]); // } // return Expression.Call(operands[0], // typeof(string).GetMethod("Replace", new[] { typeof(char), typeof(char) }), // operands[1], operands[2]); //} //protected virtual Expression TranslateInsertString(List operands) //{ // return Expression.Call(operands.First(), typeof(string).GetMethod("Insert"), operands[1], operands[2]); //} //protected virtual Expression TranslateTrim(List operands) //{ // return Expression.Call(operands.First(), typeof(string).GetMethod("Trim", new Type[] { })); //} //protected virtual Expression TranslateSubString(List operands) //{ // if (operands.Count > 2) // { // return Expression.Call(operands[0], // typeof(string).GetMethod("Substring", new[] { operands[1].Type, operands[2].Type }), // operands[1], operands[2]); // } // return Expression.Call(operands[0], // typeof(string).GetMethod("Substring", new[] { operands[1].Type }), // operands[1]); //} //protected virtual Expression TranslateToLower(List operands) //{ // return Expression.Call(operands[0], typeof(string).GetMethod("ToLower", new Type[0])); //} //protected virtual Expression TranslateToUpper(List operands) //{ // return Expression.Call(operands[0], typeof(string).GetMethod("ToUpper", new Type[0])); //} protected virtual Expression TranslateConcat(List operands) { return Expression.Add(operands[0], operands[1]); } protected virtual Expression TranslateIsNotNull(List operands) { return Expression.NotEqual(operands[0], Expression.Constant(null)); } protected virtual Expression TranslateIsNull(List operands) { return Expression.Equal(operands[0], Expression.Constant(null)); } } }