/// <summary>
 /// This is a shortcut of removing the FunctionSignature through 'CustomUriFunctions' class and
 /// unbinding the function name from it's MethodInfo through 'UriFunctionsBinder' class.
 /// See these classes documentations.
 /// </summary>
 /// <param name="functionName">The uri function name that appears in the OData request uri.</param>
 /// <param name="functionSignature">The new custom function signature.</param>
 /// <param name="methodInfo">The MethodInfo to bind the given function name.</param>
 /// <exception cref="Exception">Any exception thrown by 'CustomUriFunctions.RemoveCustomUriFunction' and 'UriFunctionsBinder.UnbindUriFunctionName' methods.</exception>
 /// <returns>'True' if the fucntion signature has successfully removed and unbinded. 'False' otherwise.</returns>
 public static bool RemoveCustomUriFunction(string functionName,
     FunctionSignatureWithReturnType functionSignature, MethodInfo methodInfo)
 {
     return
         CustomUriFunctions.RemoveCustomUriFunction(functionName, functionSignature) &&
         UriFunctionsBinder.UnbindUriFunctionName(functionName, methodInfo);
 }
        /// <summary>
        /// Add a custom uri function to extend or override the built-in OData protocol of uri functions.
        /// In case the function signature already exists as a built-in function, if requested (addAsOverloadToBuiltInFunction = true), the new function signature will be added as another overload.
        /// In case the function name already exists as a custom function, the signature will be added as an another overload.
        /// </summary>
        /// <param name="customFunctionName">The new custom function name</param>
        /// <param name="newCustomFunctionSignature">The new custom function signature</param>
        /// <param name="addAsOverloadToBuiltInFunction">If 'True', add as another overload to the existing built-in function in case signature already exists</param>
        /// <exception cref="ArgumentNullException">Arguments are null, or function signature return type is null</exception>
        /// <exception cref="ODataException">Throws if built-in function name already exists, and parameter 'addAsOverloadToBuiltInFunction' is not 'True'</exception>
        /// <exception cref="ODataException">Throws if built-in function signature overload already exists.</exception>
        /// <exception cref="ODataException">Throws if custom function signature overload already exists</exception>
        public static void AddCustomUriFunction(string customFunctionName, FunctionSignatureWithReturnType newCustomFunctionSignature, bool addAsOverloadToBuiltInFunction)
        {
            // Parameters validation
            ExceptionUtils.CheckArgumentStringNotNullOrEmpty(customFunctionName, "customFunctionName");
            ExceptionUtils.CheckArgumentNotNull(newCustomFunctionSignature, "newCustomFunctionSignature");

            ValidateFunctionWithReturnType(newCustomFunctionSignature);

            // Thread saftey - before using the custom functions dictionary
            lock (Locker)
            {
                // Check if the function does already exists in the Built-In functions
                // If 'addAsOverloadToBuiltInFunction' parameter is false - throw expection
                // Else, add as a custom function
                FunctionSignatureWithReturnType[] existingBuiltInFunctionOverload;
                if (BuiltInUriFunctions.TryGetBuiltInFunction(customFunctionName, out existingBuiltInFunctionOverload))
                {
                    // Built-In function with the same signature already exists, and will not be added as an another overload by user request.
                    if (!addAsOverloadToBuiltInFunction)
                    {
                        throw new ODataException(Strings.CustomUriFunctions_AddCustomUriFunction_BuiltInExistsNotAddingAsOverload(customFunctionName));
                    }

                    // Function name exists, check if full siganture exists among the overloads.
                    if (existingBuiltInFunctionOverload.Any(builtInFunction =>
                            AreFunctionsSignatureEqual(newCustomFunctionSignature, builtInFunction)))
                    {
                        throw new ODataException(Strings.CustomUriFunctions_AddCustomUriFunction_BuiltInExistsFullSignature(customFunctionName));
                    }
                }

                AddCustomFunction(customFunctionName, newCustomFunctionSignature);
            }
        }
        public void AddCustomFunction_FunctionNameCannotBeEmptyString()
        {
            FunctionSignatureWithReturnType customFunctionSignature =
                new FunctionSignatureWithReturnType(EdmCoreModel.Instance.GetBoolean(false), EdmCoreModel.Instance.GetInt32(false));

            Action addCustomFunctionSignature = () =>
                CustomUriFunctions.AddCustomUriFunction(string.Empty, customFunctionSignature);

            addCustomFunctionSignature.ShouldThrow<ArgumentNullException>();
        }
Beispiel #4
0
        /// <summary>
        /// Creates all of the spatial functions
        /// </summary>
        /// <param name="functions">Dictionary of functions to add to.</param>
        internal static void CreateSpatialFunctions(IDictionary <string, FunctionSignatureWithReturnType[]> functions)
        {
            // double geo.distance(geographyPoint, geographyPoint)
            // double geo.distance(geometryPoint, geometryPoint)
            FunctionSignatureWithReturnType[] signatures = new FunctionSignatureWithReturnType[]
            {
                new FunctionSignatureWithReturnType(
                    EdmCoreModel.Instance.GetDouble(true),
                    EdmCoreModel.Instance.GetSpatial(EdmPrimitiveTypeKind.GeographyPoint, true),
                    EdmCoreModel.Instance.GetSpatial(EdmPrimitiveTypeKind.GeographyPoint, true)),
                new FunctionSignatureWithReturnType(
                    EdmCoreModel.Instance.GetDouble(true),
                    EdmCoreModel.Instance.GetSpatial(EdmPrimitiveTypeKind.GeometryPoint, true),
                    EdmCoreModel.Instance.GetSpatial(EdmPrimitiveTypeKind.GeometryPoint, true))
            };
            functions.Add("geo.distance", signatures);

            // bool geo.intersects(geometry.Point, geometry.Polygon)
            // bool geo.intersects(geometry.Polygon, geomtery.Point)
            // bool geo.intersects(geography.Point, geography.Polygon)
            // bool geo.intersects(geography.Polygon, geography.Point)
            signatures = new FunctionSignatureWithReturnType[]
            {
                new FunctionSignatureWithReturnType(
                    EdmCoreModel.Instance.GetBoolean(true),
                    EdmCoreModel.Instance.GetSpatial(EdmPrimitiveTypeKind.GeometryPoint, true),
                    EdmCoreModel.Instance.GetSpatial(EdmPrimitiveTypeKind.GeometryPolygon, true)),
                new FunctionSignatureWithReturnType(
                    EdmCoreModel.Instance.GetBoolean(true),
                    EdmCoreModel.Instance.GetSpatial(EdmPrimitiveTypeKind.GeometryPolygon, true),
                    EdmCoreModel.Instance.GetSpatial(EdmPrimitiveTypeKind.GeometryPoint, true)),
                new FunctionSignatureWithReturnType(
                    EdmCoreModel.Instance.GetBoolean(true),
                    EdmCoreModel.Instance.GetSpatial(EdmPrimitiveTypeKind.GeographyPoint, true),
                    EdmCoreModel.Instance.GetSpatial(EdmPrimitiveTypeKind.GeographyPolygon, true)),
                new FunctionSignatureWithReturnType(
                    EdmCoreModel.Instance.GetBoolean(true),
                    EdmCoreModel.Instance.GetSpatial(EdmPrimitiveTypeKind.GeographyPolygon, true),
                    EdmCoreModel.Instance.GetSpatial(EdmPrimitiveTypeKind.GeographyPoint, true))
            };
            functions.Add("geo.intersects", signatures);

            // double geo.length(geometryLineString)
            // double geo.length(geographyLineString)
            signatures = new FunctionSignatureWithReturnType[]
            {
                new FunctionSignatureWithReturnType(
                    EdmCoreModel.Instance.GetDouble(true),
                    EdmCoreModel.Instance.GetSpatial(EdmPrimitiveTypeKind.GeometryLineString, true)),
                new FunctionSignatureWithReturnType(
                    EdmCoreModel.Instance.GetDouble(true),
                    EdmCoreModel.Instance.GetSpatial(EdmPrimitiveTypeKind.GeographyLineString, true)),
            };
            functions.Add("geo.length", signatures);
        }
        /// <summary>
        /// Creates all of the spatial functions
        /// </summary>
        /// <param name="functions">Dictionary of functions to add to.</param>
        internal static void CreateSpatialFunctions(IDictionary<string, FunctionSignatureWithReturnType[]> functions)
        {
            // double geo.distance(geographyPoint, geographyPoint)
            // double geo.distance(geometryPoint, geometryPoint)
            FunctionSignatureWithReturnType[] signatures = new FunctionSignatureWithReturnType[]
            {
                new FunctionSignatureWithReturnType(
                    EdmCoreModel.Instance.GetDouble(true), 
                    EdmCoreModel.Instance.GetSpatial(EdmPrimitiveTypeKind.GeographyPoint, true),
                    EdmCoreModel.Instance.GetSpatial(EdmPrimitiveTypeKind.GeographyPoint, true)),
                new FunctionSignatureWithReturnType(
                    EdmCoreModel.Instance.GetDouble(true),
                    EdmCoreModel.Instance.GetSpatial(EdmPrimitiveTypeKind.GeometryPoint, true),
                    EdmCoreModel.Instance.GetSpatial(EdmPrimitiveTypeKind.GeometryPoint, true))
            };
            functions.Add("geo.distance", signatures);

            // bool geo.intersects(geometry.Point, geometry.Polygon)
            // bool geo.intersects(geometry.Polygon, geomtery.Point)
            // bool geo.intersects(geography.Point, geography.Polygon)
            // bool geo.intersects(geography.Polygon, geography.Point)
            signatures = new FunctionSignatureWithReturnType[]
            {
                new FunctionSignatureWithReturnType(
                    EdmCoreModel.Instance.GetBoolean(true),
                    EdmCoreModel.Instance.GetSpatial(EdmPrimitiveTypeKind.GeometryPoint, true),
                    EdmCoreModel.Instance.GetSpatial(EdmPrimitiveTypeKind.GeometryPolygon, true)),
                new FunctionSignatureWithReturnType(
                    EdmCoreModel.Instance.GetBoolean(true),
                    EdmCoreModel.Instance.GetSpatial(EdmPrimitiveTypeKind.GeometryPolygon, true),
                    EdmCoreModel.Instance.GetSpatial(EdmPrimitiveTypeKind.GeometryPoint, true)),
                new FunctionSignatureWithReturnType(
                    EdmCoreModel.Instance.GetBoolean(true),
                    EdmCoreModel.Instance.GetSpatial(EdmPrimitiveTypeKind.GeographyPoint, true),
                    EdmCoreModel.Instance.GetSpatial(EdmPrimitiveTypeKind.GeographyPolygon, true)),
                new FunctionSignatureWithReturnType(
                    EdmCoreModel.Instance.GetBoolean(true),
                    EdmCoreModel.Instance.GetSpatial(EdmPrimitiveTypeKind.GeographyPolygon, true),
                    EdmCoreModel.Instance.GetSpatial(EdmPrimitiveTypeKind.GeographyPoint, true))
            };
            functions.Add("geo.intersects", signatures);

            // double geo.length(geometryLineString)
            // double geo.length(geographyLineString)
            signatures = new FunctionSignatureWithReturnType[]
            {
                new FunctionSignatureWithReturnType(
                    EdmCoreModel.Instance.GetDouble(true),
                    EdmCoreModel.Instance.GetSpatial(EdmPrimitiveTypeKind.GeometryLineString, true)),
                new FunctionSignatureWithReturnType(
                    EdmCoreModel.Instance.GetDouble(true),
                    EdmCoreModel.Instance.GetSpatial(EdmPrimitiveTypeKind.GeographyLineString, true)), 
            };
            functions.Add("geo.length", signatures);
        }
        public void AddCustomFunction_CannotAddFunctionSignatureWithNullReturnType()
        {
            FunctionSignatureWithReturnType customFunctionSignatureWithNullReturnType =
                new FunctionSignatureWithReturnType(null, EdmCoreModel.Instance.GetInt32(false));

            Action addCustomFunctionSignature = () =>
                CustomUriFunctions.AddCustomUriFunction("my.customFunctionWithNoReturnType",
                                                        customFunctionSignatureWithNullReturnType);

            addCustomFunctionSignature.ShouldThrow<ArgumentNullException>();
        }
Beispiel #7
0
        /// <summary>
        /// Builds an array of signatures for date time functions.
        /// </summary>
        /// <returns>The array of signatures for a date time functions.</returns>
        private static FunctionSignatureWithReturnType[] CreateDateTimeFunctionSignatureArray()
        {
            FunctionSignatureWithReturnType dateTimeOffsetNonNullable = new FunctionSignatureWithReturnType(
                EdmCoreModel.Instance.GetInt32(false),
                EdmCoreModel.Instance.GetTemporal(EdmPrimitiveTypeKind.DateTimeOffset, false));

            FunctionSignatureWithReturnType dateTimeOffsetNullable = new FunctionSignatureWithReturnType(
                EdmCoreModel.Instance.GetInt32(false),
                EdmCoreModel.Instance.GetTemporal(EdmPrimitiveTypeKind.DateTimeOffset, true));

            return(new[] { dateTimeOffsetNonNullable, dateTimeOffsetNullable });
        }
Beispiel #8
0
        /// <summary>
        /// Builds an array of signatures for math functions.
        /// </summary>
        /// <returns>The array of signatures for math functions.</returns>
        private static FunctionSignatureWithReturnType[] CreateMathFunctionSignatureArray()
        {
            FunctionSignatureWithReturnType doubleSignature = new FunctionSignatureWithReturnType(
                EdmCoreModel.Instance.GetDouble(false),
                EdmCoreModel.Instance.GetDouble(false));
            FunctionSignatureWithReturnType nullableDoubleSignature = new FunctionSignatureWithReturnType(
                EdmCoreModel.Instance.GetDouble(false),
                EdmCoreModel.Instance.GetDouble(true));
            FunctionSignatureWithReturnType decimalSignature = new FunctionSignatureWithReturnType(
                EdmCoreModel.Instance.GetDecimal(false),
                EdmCoreModel.Instance.GetDecimal(false));
            FunctionSignatureWithReturnType nullableDecimalSignature = new FunctionSignatureWithReturnType(
                EdmCoreModel.Instance.GetDecimal(false),
                EdmCoreModel.Instance.GetDecimal(true));

            return(new FunctionSignatureWithReturnType[] { doubleSignature, decimalSignature, nullableDoubleSignature, nullableDecimalSignature });
        }
        /// <summary>
        /// This is a shortcut of adding the custom FunctionSignature through 'CustomUriFunctions' class and
        /// binding the function name to it's MethodInfo through 'UriFunctionsBinder' class.
        /// See these classes documentations.
        /// In case of an excpetion, both operations(adding the signature and binding the function) will be undone.
        /// </summary>
        /// <param name="functionName">The uri function name that appears in the OData request uri.</param>
        /// <param name="functionSignature">The new custom function signature.</param>
        /// <param name="methodInfo">The MethodInfo to bind the given function name.</param>
        /// <exception cref="Exception">Any exception thrown by 'CustomUriFunctions.AddCustomUriFunction' and 'UriFunctionBinder.BindUriFunctionName' methods.</exception>
        public static void AddCustomUriFunction(string functionName,
            FunctionSignatureWithReturnType functionSignature, MethodInfo methodInfo)
        {
            try
            {
                // Add to OData.Libs function signature
                CustomUriFunctions.AddCustomUriFunction(functionName, functionSignature);

                // Bind the method to it's MethoInfo 
                UriFunctionsBinder.BindUriFunctionName(functionName, methodInfo);
            }
            catch
            {
                // Clear in case of excpetion
                RemoveCustomUriFunction(functionName, functionSignature, methodInfo);
                throw;
            }
        }
Beispiel #10
0
        /// <summary>
        /// Removes the specific function overload from the custum uri functions.
        /// </summary>
        /// <param name="functionName">Custom function name to remove</param>
        /// <param name="functionSignature">The specific signature overload of the function to remove</param>
        /// <returns>'False' if custom function signature doesn't exist. 'True' if function has been removed successfully</returns>
        /// <exception cref="ArgumentNullException">Arguments are null, or function signature return type is null</exception>
        public static bool RemoveCustomUriFunction(string functionName, FunctionSignatureWithReturnType functionSignature)
        {
            ExceptionUtils.CheckArgumentStringNotNullOrEmpty(functionName, "customFunctionName");
            ExceptionUtils.CheckArgumentNotNull(functionSignature, "customFunctionSignature");

            ValidateFunctionWithReturnType(functionSignature);

            lock (Locker)
            {
                FunctionSignatureWithReturnType[] existingCustomFunctionOverloads;
                if (!CustomFunctions.TryGetValue(functionName, out existingCustomFunctionOverloads))
                {
                    return(false);
                }

                // Get all function sigature overloads without the overload which is requested to be removed
                FunctionSignatureWithReturnType[] customFunctionOverloadsWithoutTheOneToRemove =
                    existingCustomFunctionOverloads.SkipWhile(funcOverload => AreFunctionsSignatureEqual(funcOverload, functionSignature)).ToArray();

                // Nothing was removed - Requested overload doesn't exist
                if (customFunctionOverloadsWithoutTheOneToRemove.Length == existingCustomFunctionOverloads.Length)
                {
                    return(false);
                }

                // No overloads have left in this function name. Delete the function name
                if (customFunctionOverloadsWithoutTheOneToRemove.Length == 0)
                {
                    return(CustomFunctions.Remove(functionName));
                }
                else
                {
                    // Requested overload has been removed.
                    // Update the custom functions to the overloads wihtout that one requested to be removed
                    CustomFunctions[functionName] = customFunctionOverloadsWithoutTheOneToRemove;
                    return(true);
                }
            }
        }
Beispiel #11
0
        /// <summary>
        /// Removes the specific function overload from the custum uri functions.
        /// </summary>
        /// <param name="functionName">Custom function name to remove</param>
        /// <param name="functionSignature">The specific signature overload of the function to remove</param>
        /// <returns>'False' if custom function signature doesn't exist. 'True' if function has been removed successfully</returns>
        /// <exception cref="ArgumentNullException">Arguments are null, or function signature return type is null</exception>
        public static bool RemoveCustomUriFunction(string functionName, FunctionSignatureWithReturnType functionSignature)
        {
            ExceptionUtils.CheckArgumentStringNotNullOrEmpty(functionName, "customFunctionName");
            ExceptionUtils.CheckArgumentNotNull(functionSignature, "customFunctionSignature");

            ValidateFunctionWithReturnType(functionSignature);

            lock (Locker)
            {
                FunctionSignatureWithReturnType[] existingCustomFunctionOverloads;
                if (!CustomFunctions.TryGetValue(functionName, out existingCustomFunctionOverloads))
                {
                    return false;
                }

                // Get all function sigature overloads without the overload which is requested to be removed
                FunctionSignatureWithReturnType[] customFunctionOverloadsWithoutTheOneToRemove =
                    existingCustomFunctionOverloads.SkipWhile(funcOverload => AreFunctionsSignatureEqual(funcOverload, functionSignature)).ToArray();

                // Nothing was removed - Requested overload doesn't exist
                if (customFunctionOverloadsWithoutTheOneToRemove.Length == existingCustomFunctionOverloads.Length)
                {
                    return false;
                }

                // No overloads have left in this function name. Delete the function name
                if (customFunctionOverloadsWithoutTheOneToRemove.Length == 0)
                {
                    return CustomFunctions.Remove(functionName);
                }
                else
                {
                    // Requested overload has been removed.
                    // Update the custom functions to the overloads wihtout that one requested to be removed
                    CustomFunctions[functionName] = customFunctionOverloadsWithoutTheOneToRemove;
                    return true;
                }
            }
        }
        public void RemoveCustomFunction_FunctionSignatureWithoutAReturnType()
        {
            FunctionSignatureWithReturnType existingCustomFunctionSignature =
                   new FunctionSignatureWithReturnType(null, EdmCoreModel.Instance.GetBoolean(false));

            // Test
            Action removeFunction = () =>
                CustomUriFunctions.RemoveCustomUriFunction("FunctionName", existingCustomFunctionSignature);

            // Assert
            removeFunction.ShouldThrow<ArgumentNullException>();
        }
        /// <summary>
        /// Returns a list of signatures for a function name.
        /// </summary>
        /// <param name="name">The name of the function to look for.</param>
        /// <param name="signatures">The list of signatures available for the function name.</param>
        /// <returns>true if the function was found, or false otherwise.</returns>
        internal static bool TryGetCustomFunction(string name, out FunctionSignatureWithReturnType[] signatures)
        {
            Debug.Assert(name != null, "name != null");

            lock (Locker)
            {
                return CustomFunctions.TryGetValue(name, out signatures);
            }
        }
        public void AddCustomFunction_CustomFunctionDoesntExist_ShouldAdd_NoArgumnetsToFunctionSignature()
        {
            string customFunctionName = "my.NewCustomFunction";
            try
            {
                // New not existing custom function - function without any argumnets
                var newCustomFunctionSignature =
                    new FunctionSignatureWithReturnType(EdmCoreModel.Instance.GetDouble(false));
                CustomUriFunctions.AddCustomUriFunction(customFunctionName, newCustomFunctionSignature);

                // Assert
                // Make sure both signatures exists
                FunctionSignatureWithReturnType[] customFunctionSignatures =
                    GetCustomFunctionSignaturesOrNull(customFunctionName);

                customFunctionSignatures.Length.Should().Be(1);
                customFunctionSignatures[0].Should().BeSameAs(newCustomFunctionSignature);
            }
            finally
            {
                // Clean from CustomUriFunctions cache
                CustomUriFunctions.RemoveCustomUriFunction(customFunctionName);
            }
        }
        public void ParseWithCustomUriFunction()
        {
            try
            {
                FunctionSignatureWithReturnType myStringFunction
                    = new FunctionSignatureWithReturnType(EdmCoreModel.Instance.GetBoolean(true), EdmCoreModel.Instance.GetString(true), EdmCoreModel.Instance.GetString(true));

                // Add a custom uri function
                CustomUriFunctions.AddCustomUriFunction("mystringfunction", myStringFunction);

                var fullUri = new Uri("http://www.odata.com/OData/People" + "?$filter=mystringfunction(Name, 'BlaBla')");
                ODataUriParser parser = new ODataUriParser(HardCodedTestModel.TestModel, new Uri("http://www.odata.com/OData/"), fullUri);

                var startsWithArgs = parser.ParseFilter().Expression.ShouldBeSingleValueFunctionCallQueryNode("mystringfunction").And.Parameters.ToList();
                startsWithArgs[0].ShouldBeSingleValuePropertyAccessQueryNode(HardCodedTestModel.GetPersonNameProp());
                startsWithArgs[1].ShouldBeConstantQueryNode("BlaBla");
            }
            finally
            {
                CustomUriFunctions.RemoveCustomUriFunction("mystringfunction").Should().BeTrue();
            }
        }
        public void AddCustomFunction_CustomFunctionNameExistsButNotFullSignature_ShouldAddAsAnOverload()
        {
            string customFunctionName = "my.ExistingCustomFunction";
            try
            {
                // Prepare
                FunctionSignatureWithReturnType existingCustomFunctionSignature =
                    new FunctionSignatureWithReturnType(EdmCoreModel.Instance.GetDouble(false), EdmCoreModel.Instance.GetBoolean(false));
                CustomUriFunctions.AddCustomUriFunction(customFunctionName, existingCustomFunctionSignature);

                //Test
                // Same name, but different signature
                var newCustomFunctionSignature =
                    new FunctionSignatureWithReturnType(EdmCoreModel.Instance.GetDouble(false), EdmCoreModel.Instance.GetInt32(false), EdmCoreModel.Instance.GetBoolean(false));
                CustomUriFunctions.AddCustomUriFunction(customFunctionName, newCustomFunctionSignature);

                // Assert
                // Make sure both signatures exists
                bool areSiganturesAdded =
                    GetCustomFunctionSignaturesOrNull(customFunctionName).
                        All(x => x.Equals(existingCustomFunctionSignature) || x.Equals(newCustomFunctionSignature));

                areSiganturesAdded.Should().BeTrue();
            }
            finally
            {
                // Clean both signatures from CustomUriFunctions cache
                CustomUriFunctions.RemoveCustomUriFunction(customFunctionName);
            }
        }
        /// <summary>
        /// Builds an array of signatures for date time functions.
        /// </summary>
        /// <returns>The array of signatures for a date time functions.</returns>
        private static FunctionSignatureWithReturnType[] CreateDateTimeFunctionSignatureArray()
        {
            FunctionSignatureWithReturnType dateTimeOffsetNonNullable = new FunctionSignatureWithReturnType(
                EdmCoreModel.Instance.GetInt32(false),
                EdmCoreModel.Instance.GetTemporal(EdmPrimitiveTypeKind.DateTimeOffset, false));

            FunctionSignatureWithReturnType dateTimeOffsetNullable = new FunctionSignatureWithReturnType(
                EdmCoreModel.Instance.GetInt32(false),
                EdmCoreModel.Instance.GetTemporal(EdmPrimitiveTypeKind.DateTimeOffset, true));

            return new[] { dateTimeOffsetNonNullable, dateTimeOffsetNullable };
        }
Beispiel #18
0
        private static bool AreFunctionsSignatureEqual(FunctionSignatureWithReturnType functionOne, FunctionSignatureWithReturnType functionTwo)
        {
            Debug.Assert(functionOne != null, "functionOne != null");
            Debug.Assert(functionTwo != null, "functionTwo != null");

            // Check if ReturnTypes are equal
            if (!functionOne.ReturnType.IsEquivalentTo(functionTwo.ReturnType))
            {
                return(false);
            }

            // Check the length of the Arguments of the two functions
            if (functionOne.ArgumentTypes.Length != functionTwo.ArgumentTypes.Length)
            {
                return(false);
            }

            // Check if the arguments are equal
            for (int argumentIndex = 0; argumentIndex < functionOne.ArgumentTypes.Length; argumentIndex++)
            {
                if (!functionOne.ArgumentTypes[argumentIndex].IsEquivalentTo(functionTwo.ArgumentTypes[argumentIndex]))
                {
                    return(false);
                }
            }

            return(true);
        }
        /// <summary>
        /// Check if FunctionSignatureWithReturnType is valid.
        /// Vaild if the signature has a ReturnType
        /// </summary>
        /// <param name="functionSignature">Function signature to validate</param>
        private static void ValidateFunctionWithReturnType(FunctionSignatureWithReturnType functionSignature)
        {
            if (functionSignature == null)
            {
                return;
            }

            ExceptionUtils.CheckArgumentNotNull(functionSignature.ReturnType, "functionSignatureWithReturnType must contain a return type");
        }
Beispiel #20
0
        /// <summary>
        /// Creates all string functions.
        /// </summary>
        /// <param name="functions">Dictionary of functions to add to.</param>
        private static void CreateStringFunctions(IDictionary <string, FunctionSignatureWithReturnType[]> functions)
        {
            FunctionSignatureWithReturnType signature;

            FunctionSignatureWithReturnType[] signatures;

            // bool endswith(string, string)
            signature = new FunctionSignatureWithReturnType(
                EdmCoreModel.Instance.GetBoolean(false),
                EdmCoreModel.Instance.GetString(true),
                EdmCoreModel.Instance.GetString(true));
            functions.Add("endswith", new FunctionSignatureWithReturnType[] { signature });

            // int indexof(string, string)
            signature = new FunctionSignatureWithReturnType(
                EdmCoreModel.Instance.GetInt32(false),
                EdmCoreModel.Instance.GetString(true),
                EdmCoreModel.Instance.GetString(true));
            functions.Add("indexof", new FunctionSignatureWithReturnType[] { signature });

            // string replace(string, string, string)
            signature = new FunctionSignatureWithReturnType(
                EdmCoreModel.Instance.GetString(true),
                EdmCoreModel.Instance.GetString(true),
                EdmCoreModel.Instance.GetString(true),
                EdmCoreModel.Instance.GetString(true));
            functions.Add("replace", new FunctionSignatureWithReturnType[] { signature });

            // bool startswith(string, string)
            signature = new FunctionSignatureWithReturnType(
                EdmCoreModel.Instance.GetBoolean(false),
                EdmCoreModel.Instance.GetString(true),
                EdmCoreModel.Instance.GetString(true));
            functions.Add("startswith", new FunctionSignatureWithReturnType[] { signature });

            // string tolower(string)
            signature = new FunctionSignatureWithReturnType(
                EdmCoreModel.Instance.GetString(true),
                EdmCoreModel.Instance.GetString(true));
            functions.Add("tolower", new FunctionSignatureWithReturnType[] { signature });

            // string toupper(string)
            signature = new FunctionSignatureWithReturnType(
                EdmCoreModel.Instance.GetString(true),
                EdmCoreModel.Instance.GetString(true));
            functions.Add("toupper", new FunctionSignatureWithReturnType[] { signature });

            // string trim(string)
            signature = new FunctionSignatureWithReturnType(
                EdmCoreModel.Instance.GetString(true),
                EdmCoreModel.Instance.GetString(true));
            functions.Add("trim", new FunctionSignatureWithReturnType[] { signature });

            signatures = new FunctionSignatureWithReturnType[]
            {
                // string substring(string, int)
                new FunctionSignatureWithReturnType(
                    EdmCoreModel.Instance.GetString(true),
                    EdmCoreModel.Instance.GetString(true),
                    EdmCoreModel.Instance.GetInt32(false)),

                // string substring(string, int?)
                new FunctionSignatureWithReturnType(
                    EdmCoreModel.Instance.GetString(true),
                    EdmCoreModel.Instance.GetString(true),
                    EdmCoreModel.Instance.GetInt32(true)),

                // string substring(string, int, int)
                new FunctionSignatureWithReturnType(
                    EdmCoreModel.Instance.GetString(true),
                    EdmCoreModel.Instance.GetString(true),
                    EdmCoreModel.Instance.GetInt32(false),
                    EdmCoreModel.Instance.GetInt32(false)),

                // string substring(string, int?, int)
                new FunctionSignatureWithReturnType(
                    EdmCoreModel.Instance.GetString(true),
                    EdmCoreModel.Instance.GetString(true),
                    EdmCoreModel.Instance.GetInt32(true),
                    EdmCoreModel.Instance.GetInt32(false)),

                // string substring(string, int, int?)
                new FunctionSignatureWithReturnType(
                    EdmCoreModel.Instance.GetString(true),
                    EdmCoreModel.Instance.GetString(true),
                    EdmCoreModel.Instance.GetInt32(false),
                    EdmCoreModel.Instance.GetInt32(true)),

                // string substring(string, int?, int?)
                new FunctionSignatureWithReturnType(
                    EdmCoreModel.Instance.GetString(true),
                    EdmCoreModel.Instance.GetString(true),
                    EdmCoreModel.Instance.GetInt32(true),
                    EdmCoreModel.Instance.GetInt32(true)),
            };
            functions.Add("substring", signatures);

            // bool contains(string, string)
            signature = new FunctionSignatureWithReturnType(
                EdmCoreModel.Instance.GetBoolean(false),
                EdmCoreModel.Instance.GetString(true),
                EdmCoreModel.Instance.GetString(true));
            functions.Add("contains", new FunctionSignatureWithReturnType[] { signature });

            // string concat(string, string)
            signature = new FunctionSignatureWithReturnType(
                EdmCoreModel.Instance.GetString(true),
                EdmCoreModel.Instance.GetString(true),
                EdmCoreModel.Instance.GetString(true));
            functions.Add("concat", new FunctionSignatureWithReturnType[] { signature });

            // int length(string)
            signature = new FunctionSignatureWithReturnType(
                EdmCoreModel.Instance.GetInt32(false),
                EdmCoreModel.Instance.GetString(true));
            functions.Add("length", new FunctionSignatureWithReturnType[] { signature });
        }
        public void RemoveCustomFunction_RemoveFunctionWithSameNameAndSignature()
        {
            string customFunctionName = "my.ExistingCustomFunction";

            try
            {
                // Prepare
                FunctionSignatureWithReturnType existingCustomFunctionSignature =
                        new FunctionSignatureWithReturnType(EdmCoreModel.Instance.GetDouble(false), EdmCoreModel.Instance.GetBoolean(false));
                CustomUriFunctions.AddCustomUriFunction(customFunctionName, existingCustomFunctionSignature);

                GetCustomFunctionSignaturesOrNull(customFunctionName)[0].Equals(existingCustomFunctionSignature).Should().BeTrue();

                // Test
                bool isRemoveSucceeded = CustomUriFunctions.RemoveCustomUriFunction(customFunctionName, existingCustomFunctionSignature);

                // Assert
                isRemoveSucceeded.Should().BeTrue();

                GetCustomFunctionSignaturesOrNull(customFunctionName).Should().BeNull();
            }
            finally
            {
                CustomUriFunctions.RemoveCustomUriFunction(customFunctionName);
            }
        }
        /// <summary>Finds the best fitting function for the specified arguments.</summary>
        /// <param name="functions">Functions to consider.</param>
        /// <param name="argumentNodes">Nodes of the arguments for the function, can be new {null,null}.</param>
        /// <returns>The best fitting function; null if none found or ambiguous.</returns>
        internal static FunctionSignatureWithReturnType FindBestFunctionSignature(FunctionSignatureWithReturnType[] functions, SingleValueNode[] argumentNodes)
        {
            IEdmTypeReference[] argumentTypes = argumentNodes.Select(s => s.TypeReference).ToArray();
            Debug.Assert(functions != null, "functions != null");
            Debug.Assert(argumentTypes != null, "argumentTypes != null");
            List<FunctionSignatureWithReturnType> applicableFunctions = new List<FunctionSignatureWithReturnType>(functions.Length);

            // Build a list of applicable functions (and cache their promoted arguments).
            foreach (FunctionSignatureWithReturnType candidate in functions)
            {
                if (candidate.ArgumentTypes.Length != argumentTypes.Length)
                {
                    continue;
                }

                bool argumentsMatch = true;
                for (int i = 0; i < candidate.ArgumentTypes.Length; i++)
                {
                    if (!CanPromoteNodeTo(argumentNodes[i], argumentTypes[i], candidate.ArgumentTypes[i]))
                    {
                        argumentsMatch = false;
                        break;
                    }
                }

                if (argumentsMatch)
                {
                    applicableFunctions.Add(candidate);
                }
            }

            // Return the best applicable function.
            if (applicableFunctions.Count == 0)
            {
                // No matching function.
                return null;
            }
            else if (applicableFunctions.Count == 1)
            {
                return applicableFunctions[0];
            }
            else
            {
                // Find a single function which is better than all others.
                int bestFunctionIndex = -1;
                for (int i = 0; i < applicableFunctions.Count; i++)
                {
                    bool betterThanAllOthers = true;
                    for (int j = 0; j < applicableFunctions.Count; j++)
                    {
                        if (i != j && MatchesArgumentTypesBetterThan(argumentTypes, applicableFunctions[j].ArgumentTypes, applicableFunctions[i].ArgumentTypes))
                        {
                            betterThanAllOthers = false;
                            break;
                        }
                    }

                    if (betterThanAllOthers)
                    {
                        if (bestFunctionIndex == -1)
                        {
                            bestFunctionIndex = i;
                        }
                        else
                        {
                            // This means there were at least 2 equally matching functions.
                            return null;
                        }
                    }
                }

                if (bestFunctionIndex == -1)
                {
                    return null;
                }

                return applicableFunctions[bestFunctionIndex];
            }
        }
        public void AddCustomFunction_CannotAddFunctionWithNameAlreadyExistsAsBuildIsFunction_AddAsOverloadFalse_SameNameDifferentArguments()
        {
            FunctionSignatureWithReturnType customFunctionSignature =
                new FunctionSignatureWithReturnType(EdmCoreModel.Instance.GetDouble(false),
                                                    EdmCoreModel.Instance.GetBoolean(false));

            Action addExistingCustomFunctionSignature = () =>
                CustomUriFunctions.AddCustomUriFunction(BUILT_IN_GEODISTANCE_FUNCTION_NAME, customFunctionSignature);

            addExistingCustomFunctionSignature.ShouldThrow<ODataException>().
                WithMessage(Strings.CustomUriFunctions_AddCustomUriFunction_BuiltInExistsNotAddingAsOverload(BUILT_IN_GEODISTANCE_FUNCTION_NAME));
        }
        public void RemoveCustomFunction_RemoveFunctionWithSameNameAndSignature_OtherOverloadsExists()
        {
            string customFunctionName = "my.ExistingCustomFunction";

            try
            {
                // Prepare
                FunctionSignatureWithReturnType existingCustomFunctionSignature =
                        new FunctionSignatureWithReturnType(EdmCoreModel.Instance.GetDouble(false), EdmCoreModel.Instance.GetBoolean(false));
                CustomUriFunctions.AddCustomUriFunction(customFunctionName, existingCustomFunctionSignature);

                FunctionSignatureWithReturnType existingCustomFunctionSignatureTwo =
                    new FunctionSignatureWithReturnType(EdmCoreModel.Instance.GetBoolean(false), EdmCoreModel.Instance.GetDate(false));
                CustomUriFunctions.AddCustomUriFunction(customFunctionName, existingCustomFunctionSignatureTwo);

                // Validate that the two overloads as 
                GetCustomFunctionSignaturesOrNull(customFunctionName).
                    All(funcSignature =>    funcSignature.Equals(existingCustomFunctionSignature) ||
                                            funcSignature.Equals(existingCustomFunctionSignatureTwo)).
                        Should().BeTrue();

                // Remove the first overload, second overload should not be removed
                bool isRemoveSucceeded = CustomUriFunctions.RemoveCustomUriFunction(customFunctionName, existingCustomFunctionSignature);

                // Assert
                isRemoveSucceeded.Should().BeTrue();

                FunctionSignatureWithReturnType[] overloads = GetCustomFunctionSignaturesOrNull(customFunctionName);
                overloads.Length.Should().Be(1);
                overloads[0].Should().Be(existingCustomFunctionSignatureTwo);
            }
            finally
            {
                // Clean up cache
                CustomUriFunctions.RemoveCustomUriFunction(customFunctionName);
            }
        }
        private static void AddCustomFunction(string customFunctionName, FunctionSignatureWithReturnType newCustomFunctionSignature)
        {
            FunctionSignatureWithReturnType[] existingCustomFunctionOverloads;

            // In case the function doesn't already exist
            if (!CustomFunctions.TryGetValue(customFunctionName, out existingCustomFunctionOverloads))
            {
                CustomFunctions.Add(customFunctionName, new FunctionSignatureWithReturnType[] { newCustomFunctionSignature });
            }
            else
            {
                // Function does already exist as a custom function in cache
                // Check if the function overload doesn't already exist
                bool isOverloadAlreadyExist =
                    existingCustomFunctionOverloads.Any(existingFunction => AreFunctionsSignatureEqual(existingFunction, newCustomFunctionSignature));

                if (isOverloadAlreadyExist)
                {
                    // Throw if already exists - User is stupid (inserted the same function twice)
                    throw new ODataException(Strings.CustomUriFunctions_AddCustomUriFunction_CustomFunctionOverloadExists(customFunctionName));
                }

                // Add the custom function as an overload to the same function name
                CustomFunctions[customFunctionName] = 
                    existingCustomFunctionOverloads.Concat(new FunctionSignatureWithReturnType[] { newCustomFunctionSignature }).ToArray();
            }
        }
        public void RemoveCustomFunction_CannotRemoveFunctionWithSameNameAndDifferentSignature()
        {
            string customFunctionName = "my.ExistingCustomFunction";

            try
            {
                // Prepare
                FunctionSignatureWithReturnType existingCustomFunctionSignature =
                        new FunctionSignatureWithReturnType(EdmCoreModel.Instance.GetDouble(false), EdmCoreModel.Instance.GetBoolean(false));
                CustomUriFunctions.AddCustomUriFunction(customFunctionName, existingCustomFunctionSignature);

                GetCustomFunctionSignaturesOrNull(customFunctionName)[0].Equals(existingCustomFunctionSignature).Should().BeTrue();

                // Function with different siganture
                FunctionSignatureWithReturnType customFunctionSignatureToRemove =
                        new FunctionSignatureWithReturnType(EdmCoreModel.Instance.GetInt16(false), EdmCoreModel.Instance.GetBoolean(false));

                // Test

                // Try Remove a function with the same name but different siganture
                bool isRemoveSucceeded = CustomUriFunctions.RemoveCustomUriFunction(customFunctionName, customFunctionSignatureToRemove);

                // Assert
                isRemoveSucceeded.Should().BeFalse();
            }
            finally
            {
                // Clean up cahce
                CustomUriFunctions.RemoveCustomUriFunction(customFunctionName);
            }

        }
        private static bool AreFunctionsSignatureEqual(FunctionSignatureWithReturnType functionOne, FunctionSignatureWithReturnType functionTwo)
        {
            Debug.Assert(functionOne != null, "functionOne != null");
            Debug.Assert(functionTwo != null, "functionTwo != null");

            // Check if ReturnTypes are equal
            if (!functionOne.ReturnType.IsEquivalentTo(functionTwo.ReturnType))
            {
                return false;
            }

            // Check the length of the Arguments of the two functions
            if (functionOne.ArgumentTypes.Length != functionTwo.ArgumentTypes.Length)
            {
                return false;
            }

            // Check if the arguments are equal
            for (int argumentIndex = 0; argumentIndex < functionOne.ArgumentTypes.Length; argumentIndex++)
            {
                if (!functionOne.ArgumentTypes[argumentIndex].IsEquivalentTo(functionTwo.ArgumentTypes[argumentIndex]))
                {
                    return false;
                }
            }

            return true;
        }
        public void GetUriFunction_CombineCustomFunctionsAndBuiltInFunctions()
        {
            const string BUILT_IN_GEODISTANCE_FUNCTION_NAME = "geo.distance";

            try
            {
                FunctionSignatureWithReturnType customFunctionSignature =
                    new FunctionSignatureWithReturnType(EdmCoreModel.Instance.GetDouble(false),
                                                        EdmCoreModel.Instance.GetBoolean(false));

                // Add with 'addAsOverload' 'true'
                CustomUriFunctions.AddCustomUriFunction(BUILT_IN_GEODISTANCE_FUNCTION_NAME, customFunctionSignature, true);

                
                FunctionSignatureWithReturnType[] resultUriFunctionSignatures =
                    FunctionCallBinder.GetUriFunctionSignatures(BUILT_IN_GEODISTANCE_FUNCTION_NAME);

                // Assert
                FunctionSignatureWithReturnType[] existsBuiltInSignature;
                BuiltInUriFunctions.TryGetBuiltInFunction(BUILT_IN_GEODISTANCE_FUNCTION_NAME, out existsBuiltInSignature).Should().BeTrue();

                resultUriFunctionSignatures.Should().NotBeNull();
                resultUriFunctionSignatures.Length.Should().Be(existsBuiltInSignature.Length + 1);
                resultUriFunctionSignatures.All(x => x == customFunctionSignature || existsBuiltInSignature.Any(y => x == y)).Should().BeTrue();
            }
            finally
            {
                // Clean from CustomFunctions cache
                CustomUriFunctions.RemoveCustomUriFunction(BUILT_IN_GEODISTANCE_FUNCTION_NAME);
            }
        }
 /// <summary>
 /// Add a custom uri function to extend uri functions.
 /// In case the function name already exists as a custom function, the signature will be added as an another overload.
 /// </summary>
 /// <param name="customFunctionName">The new custom function name</param>
 /// <param name="newCustomFunctionSignature">The new custom function signature</param>
 /// <exception cref="ArgumentNullException">Arguments are null, or function signature return type is null</exception>
 /// <exception cref="ODataException">Throws if built-in function name already exists.</exception>
 /// <exception cref="ODataException">Throws if built-in function signature overload already exists.</exception>
 /// <exception cref="ODataException">Throws if custom function signature overload already exists</exception>
 public static void AddCustomUriFunction(string customFunctionName, FunctionSignatureWithReturnType newCustomFunctionSignature)
 {
     AddCustomUriFunction(customFunctionName, newCustomFunctionSignature, false);
 }
        public void GetUriFunction_OnlyCustomFunctionsExist()
        {
            const string CUSTOM_FUNCTION_NAME = "myCustomFunction";

            try
            {
                FunctionSignatureWithReturnType customFunctionSignature =
                    new FunctionSignatureWithReturnType(EdmCoreModel.Instance.GetDouble(false),
                                                        EdmCoreModel.Instance.GetBoolean(false));

                // Add with override 'true'
                CustomUriFunctions.AddCustomUriFunction(CUSTOM_FUNCTION_NAME, customFunctionSignature);


                FunctionSignatureWithReturnType[] resultUriFunctionSignatures =
                    FunctionCallBinder.GetUriFunctionSignatures(CUSTOM_FUNCTION_NAME);

                // Assert
                resultUriFunctionSignatures.Should().NotBeNull();
                resultUriFunctionSignatures.Length.Should().Be(1);
                resultUriFunctionSignatures.All(x => x == customFunctionSignature).Should().BeTrue();
            }
            finally
            {
                // Clean from CustomFunctions cache
                CustomUriFunctions.RemoveCustomUriFunction(CUSTOM_FUNCTION_NAME);
            }
        }
        /// <summary>
        /// Creates all string functions.
        /// </summary>
        /// <param name="functions">Dictionary of functions to add to.</param>
        private static void CreateStringFunctions(IDictionary<string, FunctionSignatureWithReturnType[]> functions)
        {
            FunctionSignatureWithReturnType signature;
            FunctionSignatureWithReturnType[] signatures;

            // bool endswith(string, string)
            signature = new FunctionSignatureWithReturnType(
                EdmCoreModel.Instance.GetBoolean(false),
                EdmCoreModel.Instance.GetString(true),
                EdmCoreModel.Instance.GetString(true));
            functions.Add("endswith", new FunctionSignatureWithReturnType[] { signature });

            // int indexof(string, string)
            signature = new FunctionSignatureWithReturnType(
                EdmCoreModel.Instance.GetInt32(false),
                EdmCoreModel.Instance.GetString(true),
                EdmCoreModel.Instance.GetString(true));
            functions.Add("indexof", new FunctionSignatureWithReturnType[] { signature });

            // string replace(string, string, string)
            signature = new FunctionSignatureWithReturnType(
                EdmCoreModel.Instance.GetString(true),
                EdmCoreModel.Instance.GetString(true),
                EdmCoreModel.Instance.GetString(true),
                EdmCoreModel.Instance.GetString(true));
            functions.Add("replace", new FunctionSignatureWithReturnType[] { signature });

            // bool startswith(string, string)
            signature = new FunctionSignatureWithReturnType(
                EdmCoreModel.Instance.GetBoolean(false),
                EdmCoreModel.Instance.GetString(true),
                EdmCoreModel.Instance.GetString(true));
            functions.Add("startswith", new FunctionSignatureWithReturnType[] { signature });

            // string tolower(string)
            signature = new FunctionSignatureWithReturnType(
                EdmCoreModel.Instance.GetString(true),
                EdmCoreModel.Instance.GetString(true));
            functions.Add("tolower", new FunctionSignatureWithReturnType[] { signature });

            // string toupper(string)
            signature = new FunctionSignatureWithReturnType(
                EdmCoreModel.Instance.GetString(true),
                EdmCoreModel.Instance.GetString(true));
            functions.Add("toupper", new FunctionSignatureWithReturnType[] { signature });

            // string trim(string)
            signature = new FunctionSignatureWithReturnType(
                EdmCoreModel.Instance.GetString(true),
                EdmCoreModel.Instance.GetString(true));
            functions.Add("trim", new FunctionSignatureWithReturnType[] { signature });

            signatures = new FunctionSignatureWithReturnType[] 
            {
                // string substring(string, int)
                new FunctionSignatureWithReturnType(
                    EdmCoreModel.Instance.GetString(true),
                    EdmCoreModel.Instance.GetString(true),
                    EdmCoreModel.Instance.GetInt32(false)), 

                // string substring(string, int?)
                new FunctionSignatureWithReturnType(
                    EdmCoreModel.Instance.GetString(true),
                    EdmCoreModel.Instance.GetString(true),
                    EdmCoreModel.Instance.GetInt32(true)), 

                // string substring(string, int, int)
                new FunctionSignatureWithReturnType(
                    EdmCoreModel.Instance.GetString(true),
                    EdmCoreModel.Instance.GetString(true),
                    EdmCoreModel.Instance.GetInt32(false),
                    EdmCoreModel.Instance.GetInt32(false)), 

                // string substring(string, int?, int)
                new FunctionSignatureWithReturnType(
                    EdmCoreModel.Instance.GetString(true),
                    EdmCoreModel.Instance.GetString(true),
                    EdmCoreModel.Instance.GetInt32(true),
                    EdmCoreModel.Instance.GetInt32(false)), 

                // string substring(string, int, int?)
                new FunctionSignatureWithReturnType(
                    EdmCoreModel.Instance.GetString(true),
                    EdmCoreModel.Instance.GetString(true),
                    EdmCoreModel.Instance.GetInt32(false),
                    EdmCoreModel.Instance.GetInt32(true)), 

                // string substring(string, int?, int?)
                new FunctionSignatureWithReturnType(
                    EdmCoreModel.Instance.GetString(true),
                    EdmCoreModel.Instance.GetString(true),
                    EdmCoreModel.Instance.GetInt32(true),
                    EdmCoreModel.Instance.GetInt32(true)), 
            };
            functions.Add("substring", signatures);

            // bool contains(string, string)
            signature = new FunctionSignatureWithReturnType(
                EdmCoreModel.Instance.GetBoolean(false),
                EdmCoreModel.Instance.GetString(true),
                EdmCoreModel.Instance.GetString(true));
            functions.Add("contains", new FunctionSignatureWithReturnType[] { signature });

            // string concat(string, string)
            signature = new FunctionSignatureWithReturnType(
                EdmCoreModel.Instance.GetString(true),
                EdmCoreModel.Instance.GetString(true),
                EdmCoreModel.Instance.GetString(true));
            functions.Add("concat", new FunctionSignatureWithReturnType[] { signature });

            // int length(string)
            signature = new FunctionSignatureWithReturnType(
                EdmCoreModel.Instance.GetInt32(false),
                EdmCoreModel.Instance.GetString(true));
            functions.Add("length", new FunctionSignatureWithReturnType[] { signature });
        }
 private static void AssertSignatureTypesMatchArguments(FunctionSignatureWithReturnType signature, List<QueryNode> nodes)
 {
     for (int i = 0; i < signature.ArgumentTypes.Length; ++i)
     {
         signature.ArgumentTypes[i].Definition.Should().Be(MetadataBindingUtils.GetEdmType(nodes[i]));
     }
 }
        /// <summary>
        /// Returns a list of signatures for a function name.
        /// </summary>
        /// <param name="name">The name of the function to look for.</param>
        /// <param name="signatures">The list of signatures available for the function name.</param>
        /// <returns>true if the function was found, or false otherwise.</returns>
        internal static bool TryGetBuiltInFunction(string name, out FunctionSignatureWithReturnType[] signatures)
        {
            Debug.Assert(name != null, "name != null");

            return builtInFunctions.TryGetValue(name, out signatures);
        }
        public void RemoveCustomFunction_CannotRemoveFunctionWhichDoesntExist_ByNameAndSignature()
        {
            string customFunctionName = "my.ExistingCustomFunction";
            FunctionSignatureWithReturnType customFunctionSignature =
                 new FunctionSignatureWithReturnType(EdmCoreModel.Instance.GetDouble(false), EdmCoreModel.Instance.GetBoolean(false));

            // Test
            bool isRemoveSucceeded = CustomUriFunctions.RemoveCustomUriFunction(customFunctionName, customFunctionSignature);

            // Assert
            isRemoveSucceeded.Should().BeFalse();
        }
        /// <summary>
        /// Builds an array of signatures for math functions.
        /// </summary>
        /// <returns>The array of signatures for math functions.</returns>
        private static FunctionSignatureWithReturnType[] CreateMathFunctionSignatureArray()
        {
            FunctionSignatureWithReturnType doubleSignature = new FunctionSignatureWithReturnType(
                EdmCoreModel.Instance.GetDouble(false),
                EdmCoreModel.Instance.GetDouble(false));
            FunctionSignatureWithReturnType nullableDoubleSignature = new FunctionSignatureWithReturnType(
                EdmCoreModel.Instance.GetDouble(false),
                EdmCoreModel.Instance.GetDouble(true));
            FunctionSignatureWithReturnType decimalSignature = new FunctionSignatureWithReturnType(
                EdmCoreModel.Instance.GetDecimal(false),
                EdmCoreModel.Instance.GetDecimal(false));
            FunctionSignatureWithReturnType nullableDecimalSignature = new FunctionSignatureWithReturnType(
                EdmCoreModel.Instance.GetDecimal(false),
                EdmCoreModel.Instance.GetDecimal(true));

            return new FunctionSignatureWithReturnType[] { doubleSignature, decimalSignature, nullableDoubleSignature, nullableDecimalSignature };
        }
        public void ParseWithCustomUriFunction_AddAsOverloadToBuiltIn()
        {
            FunctionSignatureWithReturnType customStartWithFunctionSignature = 
                new FunctionSignatureWithReturnType(EdmCoreModel.Instance.GetBoolean(true),
                                                    EdmCoreModel.Instance.GetString(true),
                                                    EdmCoreModel.Instance.GetInt32(true));
            try
            {
                // Add with override 'true'
                CustomUriFunctions.AddCustomUriFunction("startswith", customStartWithFunctionSignature, true);

                var fullUri = new Uri("http://www.odata.com/OData/People" + "?$filter=startswith(Name, 66)");
                ODataUriParser parser = new ODataUriParser(HardCodedTestModel.TestModel, new Uri("http://www.odata.com/OData/"), fullUri);

                var startsWithArgs = parser.ParseFilter().Expression.ShouldBeSingleValueFunctionCallQueryNode("startswith").And.Parameters.ToList();
                startsWithArgs[0].ShouldBeSingleValuePropertyAccessQueryNode(HardCodedTestModel.GetPersonNameProp());
                startsWithArgs[1].ShouldBeConstantQueryNode(66);
            }
            finally
            {
                CustomUriFunctions.RemoveCustomUriFunction("startswith").Should().BeTrue();
            }
        }