コード例 #1
0
        /// <summary>
        /// Bind path segment's operation or operationImport's parameters.
        /// </summary>
        /// <param name="configuration">The ODataUriParserConfiguration.</param>
        /// <param name="functionOrOpertion">The function or operation.</param>
        /// <param name="segmentParameterTokens">The parameter tokens to be binded.</param>
        /// <returns>The binded semantic nodes.</returns>
        internal static List <OperationSegmentParameter> BindSegmentParameters(ODataUriParserConfiguration configuration, IEdmOperation functionOrOpertion, ICollection <FunctionParameterToken> segmentParameterTokens)
        {
            // TODO: HandleComplexOrCollectionParameterValueIfExists is temp work around for single copmlex or colleciton type, it can't handle nested complex or collection value.
            ICollection <FunctionParameterToken> parametersParsed = FunctionCallBinder.HandleComplexOrCollectionParameterValueIfExists(configuration.Model, functionOrOpertion, segmentParameterTokens, configuration.Resolver.EnableCaseInsensitive, configuration.EnableUriTemplateParsing);

            // Bind it to metadata
            BindingState state = new BindingState(configuration);

            state.ImplicitRangeVariable = null;
            state.RangeVariables.Clear();
            MetadataBinder binder = new MetadataBinder(state);
            List <OperationSegmentParameter> boundParameters = new List <OperationSegmentParameter>();

            IDictionary <string, SingleValueNode> input = new Dictionary <string, SingleValueNode>(StringComparer.Ordinal);

            foreach (FunctionParameterToken paraToken in parametersParsed)
            {
                // TODO: considering another better exception
                if (paraToken.ValueToken is EndPathToken)
                {
                    throw new ODataException(Strings.MetadataBinder_ParameterNotInScope(
                                                 string.Format(CultureInfo.InvariantCulture, "{0}={1}", paraToken.ParameterName, (paraToken.ValueToken as EndPathToken).Identifier)));
                }

                SingleValueNode boundNode = (SingleValueNode)binder.Bind(paraToken.ValueToken);

                if (!input.ContainsKey(paraToken.ParameterName))
                {
                    input.Add(paraToken.ParameterName, boundNode);
                }
            }

            IDictionary <IEdmOperationParameter, SingleValueNode> result = configuration.Resolver.ResolveOperationParameters(functionOrOpertion, input);

            foreach (KeyValuePair <IEdmOperationParameter, SingleValueNode> item in result)
            {
                SingleValueNode boundNode = item.Value;

                // ensure node type is compatible with parameter type.
                IEdmTypeReference sourceTypeReference = boundNode.GetEdmTypeReference();
                bool sourceIsNullOrOpenType           = (sourceTypeReference == null);
                if (!sourceIsNullOrOpenType)
                {
                    // if the node has been rewritten, no further conversion is needed.
                    if (!TryRewriteIntegralConstantNode(ref boundNode, item.Key.Type))
                    {
                        boundNode = MetadataBindingUtils.ConvertToTypeIfNeeded(boundNode, item.Key.Type);
                    }
                }

                OperationSegmentParameter boundParamer = new OperationSegmentParameter(item.Key.Name, boundNode);
                boundParameters.Add(boundParamer);
            }

            return(boundParameters);
        }
コード例 #2
0
 /// <summary>
 /// Promotes types of arguments to match signature if possible.
 /// </summary>
 /// <param name="signature">The signature to match the types to.</param>
 /// <param name="argumentNodes">The types to promote.</param>
 internal static void TypePromoteArguments(FunctionSignatureWithReturnType signature, List <QueryNode> argumentNodes)
 {
     // Convert all argument nodes to the best signature argument type
     Debug.Assert(signature.ArgumentTypes.Length == argumentNodes.Count, "The best signature match doesn't have the same number of arguments.");
     for (int i = 0; i < argumentNodes.Count; i++)
     {
         Debug.Assert(argumentNodes[i] is SingleValueNode, "We should have already verified that all arguments are single values.");
         SingleValueNode   argumentNode          = (SingleValueNode)argumentNodes[i];
         IEdmTypeReference signatureArgumentType = signature.ArgumentTypes[i];
         Debug.Assert(signatureArgumentType.IsODataPrimitiveTypeKind() || signatureArgumentType.IsODataEnumTypeKind(), "Only primitive or enum types should be able to get here.");
         argumentNodes[i] = MetadataBindingUtils.ConvertToTypeIfNeeded(argumentNode, signatureArgumentType);
     }
 }
コード例 #3
0
        /// <summary>
        /// Binds a unary operator token.
        /// </summary>
        /// <param name="unaryOperatorToken">The unary operator token to bind.</param>
        /// <returns>The bound unary operator token.</returns>
        internal QueryNode BindUnaryOperator(UnaryOperatorToken unaryOperatorToken)
        {
            ExceptionUtils.CheckArgumentNotNull(unaryOperatorToken, "unaryOperatorToken");

            SingleValueNode operand = this.GetOperandFromToken(unaryOperatorToken);

            IEdmTypeReference typeReference = UnaryOperatorBinder.PromoteOperandType(operand, unaryOperatorToken.OperatorKind);

            Debug.Assert(typeReference == null || typeReference.IsODataPrimitiveTypeKind(), "Only primitive types should be able to get here.");
            operand = MetadataBindingUtils.ConvertToTypeIfNeeded(operand, typeReference);

            return(new UnaryOperatorNode(unaryOperatorToken.OperatorKind, operand));
        }
コード例 #4
0
        /// <summary>
        /// Binds a key property value.
        /// </summary>
        /// <param name="namedValue">The named value to bind.</param>
        /// <param name="collectionItemEntityType">The type of a single item in a collection to apply the key value to.</param>
        /// <param name="keys">Dictionary of alias to keys.</param>
        /// <param name="keyPropertyValue">The bound key property value node.</param>
        /// <returns>The bound key property value node.</returns>
        private bool TryBindKeyPropertyValue(NamedValue namedValue, IEdmEntityType collectionItemEntityType, IDictionary <string, IEdmProperty> keys, out KeyPropertyValue keyPropertyValue)
        {
            // These are exception checks because the data comes directly from the potentially user specified tree.
            ExceptionUtils.CheckArgumentNotNull(namedValue, "namedValue");
            ExceptionUtils.CheckArgumentNotNull(namedValue.Value, "namedValue.Value");
            Debug.Assert(collectionItemEntityType != null, "collectionItemType != null");

            IEdmProperty keyProperty = null;

            if (namedValue.Name == null)
            {
                foreach (IEdmProperty p in keys.Values)
                {
                    if (keyProperty == null)
                    {
                        keyProperty = p;
                    }
                    else
                    {
                        throw new ODataException(ODataErrorStrings.MetadataBinder_UnnamedKeyValueOnTypeWithMultipleKeyProperties(collectionItemEntityType.FullTypeName()));
                    }
                }
            }
            else
            {
                keyProperty = keys.SingleOrDefault(k => string.CompareOrdinal(k.Key, namedValue.Name) == 0).Value;

                if (keyProperty == null)
                {
                    keyPropertyValue = null;
                    return(false);
                }
            }

            IEdmTypeReference keyPropertyType = keyProperty.Type;

            SingleValueNode value = (SingleValueNode)this.keyValueBindMethod(namedValue.Value);

            // TODO: Check that the value is of primitive type
            Debug.Assert(keyPropertyType.IsODataPrimitiveTypeKind(), "The key's type must be primitive.");
            value = MetadataBindingUtils.ConvertToTypeIfNeeded(value, keyPropertyType);

            Debug.Assert(keyProperty != null, "keyProperty != null");
            keyPropertyValue = new KeyPropertyValue()
            {
                KeyProperty = keyProperty,
                KeyValue    = value
            };

            return(true);
        }
コード例 #5
0
        /// <summary>
        /// Promote the left and right operand types
        /// </summary>
        /// <param name="binaryOperatorKind">the operator kind</param>
        /// <param name="left">the left operand</param>
        /// <param name="right">the right operand</param>
        /// <param name="facetsPromotionRules">Promotion rules for type facets.</param>
        internal static void PromoteOperandTypes(BinaryOperatorKind binaryOperatorKind, ref SingleValueNode left, ref SingleValueNode right, TypeFacetsPromotionRules facetsPromotionRules)
        {
            IEdmTypeReference leftType;
            IEdmTypeReference rightType;

            if (!TypePromotionUtils.PromoteOperandTypes(binaryOperatorKind, left, right, out leftType, out rightType, facetsPromotionRules))
            {
                string leftTypeName  = left.TypeReference == null ? "<null>" : left.TypeReference.FullName();
                string rightTypeName = right.TypeReference == null ? "<null>" : right.TypeReference.FullName();
                throw new ODataException(ODataErrorStrings.MetadataBinder_IncompatibleOperandsError(leftTypeName, rightTypeName, binaryOperatorKind));
            }

            left  = MetadataBindingUtils.ConvertToTypeIfNeeded(left, leftType);
            right = MetadataBindingUtils.ConvertToTypeIfNeeded(right, rightType);
        }