Exemplo n.º 1
0
        /// <summary>
        /// Validate the arguments to either isof or cast
        /// </summary>
        /// <param name="state">the current state of the binding algorithm</param>
        /// <param name="isCast">flag to indicate which function we're validating</param>
        /// <param name="args">the list of arguments, which could be changed</param>
        /// <returns>the return type of the function.</returns>
        private static IEdmTypeReference ValidateIsOfOrCast(BindingState state, bool isCast, ref List <QueryNode> args)
        {
            if (args.Count != 1 && args.Count != 2)
            {
                throw new ODataErrorException(
                          ODataErrorStrings.MetadataBinder_CastOrIsOfExpressionWithWrongNumberOfOperands(args.Count));
            }

            ConstantNode typeArgument = args.Last() as ConstantNode;

            IEdmTypeReference returnType = null;

            if (typeArgument != null)
            {
                returnType = TryGetTypeReference(state.Model, typeArgument.Value as string, state.Configuration.Resolver);
            }

            if (returnType == null)
            {
                throw new ODataException(ODataErrorStrings.MetadataBinder_CastOrIsOfFunctionWithoutATypeArgument);
            }

            if (returnType.IsCollection())
            {
                throw new ODataException(ODataErrorStrings.MetadataBinder_CastOrIsOfCollectionsNotSupported);
            }

            // if we only have one argument, then add the implicit range variable as the first argument.
            if (args.Count == 1)
            {
                args = new List <QueryNode>()
                {
                    new EntityRangeVariableReferenceNode(
                        state.ImplicitRangeVariable.Name,
                        state.ImplicitRangeVariable as EntityRangeVariable),
                    args[0]
                };
            }
            else if (!(args[0] is SingleValueNode))
            {
                throw new ODataException(ODataErrorStrings.MetadataBinder_CastOrIsOfCollectionsNotSupported);
            }

            if (isCast && (args.Count == 2))
            {
                // throw if cast enum to not-string :
                if ((args[0].GetEdmTypeReference() is IEdmEnumTypeReference) &&
                    !string.Equals(typeArgument.Value as string, Microsoft.OData.Core.Metadata.EdmConstants.EdmStringTypeName, StringComparison.Ordinal))
                {
                    throw new ODataException(ODataErrorStrings.CastBinder_EnumOnlyCastToOrFromString);
                }

                // throw if cast not-string to enum :
                while (returnType is IEdmEnumTypeReference)
                {
                    IEdmTypeReference edmTypeReference = args[0].GetEdmTypeReference();
                    if (edmTypeReference == null)
                    {
                        // Support cast null to enum
                        break;
                    }

                    IEdmPrimitiveTypeReference referenceTmp = edmTypeReference as IEdmPrimitiveTypeReference;
                    if (referenceTmp != null)
                    {
                        IEdmPrimitiveType typeTmp = referenceTmp.Definition as IEdmPrimitiveType;
                        if ((typeTmp != null) && (typeTmp.PrimitiveKind == EdmPrimitiveTypeKind.String))
                        {
                            break;
                        }
                    }

                    throw new ODataException(ODataErrorStrings.CastBinder_EnumOnlyCastToOrFromString);
                }
            }

            if (isCast)
            {
                return(returnType);
            }
            else
            {
                return(EdmCoreModel.Instance.GetBoolean(true));
            }
        }