Exemple #1
0
        /// <summary>
        /// Binds a DottedIdentifierToken and it's parent node (if needed).
        /// </summary>
        /// <param name="dottedIdentifierToken">Token to bind to metadata.</param>
        /// <param name="state">State of the Binding.</param>
        /// <returns>A bound node representing the cast.</returns>
        internal QueryNode BindDottedIdentifier(DottedIdentifierToken dottedIdentifierToken, BindingState state)
        {
            DebugUtils.CheckNoExternalCallers();
            ExceptionUtils.CheckArgumentNotNull(dottedIdentifierToken, "castToken");
            ExceptionUtils.CheckArgumentNotNull(state, "state");

            QueryNode parent;
            IEdmType  parentType;

            if (dottedIdentifierToken.NextToken == null)
            {
                parent     = NodeFactory.CreateRangeVariableReferenceNode(state.ImplicitRangeVariable);
                parentType = state.ImplicitRangeVariable.TypeReference.Definition;
            }
            else
            {
                parent     = this.bindMethod(dottedIdentifierToken.NextToken);
                parentType = parent.GetEdmType();
            }

            SingleEntityNode parentAsSingleValue = parent as SingleEntityNode;

            IEdmSchemaType childType       = UriEdmHelpers.FindTypeFromModel(state.Model, dottedIdentifierToken.Identifier);
            IEdmEntityType childEntityType = childType as IEdmEntityType;

            if (childEntityType == null)
            {
                FunctionCallBinder functionCallBinder = new FunctionCallBinder(bindMethod);
                QueryNode          functionCallNode;
                if (functionCallBinder.TryBindDottedIdentifierAsFunctionCall(dottedIdentifierToken, parentAsSingleValue, state, out functionCallNode))
                {
                    return(functionCallNode);
                }
                else
                {
                    throw new ODataException(ODataErrorStrings.CastBinder_ChildTypeIsNotEntity(dottedIdentifierToken.Identifier));
                }
            }

            // Check whether childType is a derived type of the type of its parent node
            UriEdmHelpers.CheckRelatedTo(parentType, childType);

            EntityCollectionNode parentAsCollection = parent as EntityCollectionNode;

            if (parentAsCollection != null)
            {
                return(new EntityCollectionCastNode(parentAsCollection, childEntityType));
            }

            // parent can be null for casts on the implicit parameter; this is OK
            if (parent == null)
            {
                return(new SingleEntityCastNode(null, childEntityType));
            }

            Debug.Assert(parentAsSingleValue != null, "If parent of the cast node was not collection, it should be a single value.");
            return(new SingleEntityCastNode(parentAsSingleValue, childEntityType));
        }
Exemple #2
0
 /// <summary>
 /// Constructs a EndPathBinder object using the given function to bind parent token.
 /// </summary>
 /// <param name="bindMethod">Method to bind the EndPathToken's parent, if there is one.</param>
 internal EndPathBinder(MetadataBinder.QueryTokenVisitor bindMethod)
 {
     DebugUtils.CheckNoExternalCallers();
     this.bind = bindMethod;
     this.functionCallBinder = new FunctionCallBinder(bindMethod);
 }
Exemple #3
0
        /// <summary>
        /// Binds a <see cref="InnerPathToken"/>.
        /// This includes more than just navigations - it includes complex property access and primitive collections.
        /// </summary>
        /// <param name="segmentToken">The segment token to bind.</param>
        /// <param name="state">The state of binding.</param>
        /// <returns>The bound node.</returns>
        internal QueryNode BindInnerPathSegment(InnerPathToken segmentToken, BindingState state)
        {
            DebugUtils.CheckNoExternalCallers();

            FunctionCallBinder functionCallBinder = new FunctionCallBinder(this.bindMethod);

            // First we get the parent node
            QueryNode parent = this.DetermineParentNode(segmentToken, state);

            Debug.Assert(parent != null, "parent should never be null");

            SingleValueNode singleValueParent = parent as SingleValueNode;

            if (singleValueParent == null)
            {
                QueryNode boundFunction;
                if (functionCallBinder.TryBindInnerPathAsFunctionCall(segmentToken, parent, state, out boundFunction))
                {
                    return(boundFunction);
                }

                throw new ODataException(ODataErrorStrings.MetadataBinder_PropertyAccessSourceNotSingleValue(segmentToken.Identifier));
            }

            // Using the parent and name of this token, we try to get the IEdmProperty it represents
            IEdmProperty property = BindProperty(singleValueParent.TypeReference, segmentToken.Identifier);

            if (property == null)
            {
                QueryNode boundFunction;
                if (functionCallBinder.TryBindInnerPathAsFunctionCall(segmentToken, parent, state, out boundFunction))
                {
                    return(boundFunction);
                }

                if (singleValueParent.TypeReference != null && !singleValueParent.TypeReference.Definition.IsOpenType())
                {
                    throw new ODataException(
                              ODataErrorStrings.MetadataBinder_PropertyNotDeclared(
                                  parent.GetEdmTypeReference().ODataFullName(), segmentToken.Identifier));
                }

                return(new SingleValueOpenPropertyAccessNode(singleValueParent, segmentToken.Identifier));
            }

            if (property.Type.IsODataComplexTypeKind())
            {
                return(new SingleValuePropertyAccessNode(singleValueParent, property));
            }

            // Note - this means nonentity collection (primitive or complex)
            if (property.Type.IsNonEntityCollectionType())
            {
                return(new CollectionPropertyAccessNode(singleValueParent, property));
            }

            IEdmNavigationProperty navigationProperty = property as IEdmNavigationProperty;

            if (navigationProperty == null)
            {
                throw new ODataException(ODataErrorStrings.MetadataBinder_IllegalSegmentType(property.Name));
            }

            SingleEntityNode parentEntity = EnsureParentIsEntityForNavProp(singleValueParent);

            return(GetNavigationNode(navigationProperty, parentEntity, segmentToken.NamedValues, state, new KeyBinder(this.bindMethod)));
        }
Exemple #4
0
        /// <summary>
        /// Binds a function call token.
        /// </summary>
        /// <param name="functionCallToken">The function call token to bind.</param>
        /// <returns>The bound function call token.</returns>
        protected virtual QueryNode BindFunctionCall(FunctionCallToken functionCallToken)
        {
            FunctionCallBinder functionCallBinder = new FunctionCallBinder(this.Bind);

            return(functionCallBinder.BindFunctionCall(functionCallToken, this.BindingState));
        }