Beispiel #1
0
        /// <summary>
        /// Determines the parent node. If the token has a parent, that token is bound. If not, then we
        /// use the implicit parameter from the BindingState as the parent node.
        /// </summary>
        /// <param name="segmentToken">Token to determine the parent node for.</param>
        /// <param name="state">Current state of binding.</param>
        /// <returns>A SingleValueQueryNode that is the parent node of the <paramref name="segmentToken"/>.</returns>
        private QueryNode DetermineParentNode(InnerPathToken segmentToken, BindingState state)
        {
            ExceptionUtils.CheckArgumentNotNull(segmentToken, "segmentToken");
            ExceptionUtils.CheckArgumentNotNull(state, "state");

            if (segmentToken.NextToken != null)
            {
                return(this.bindMethod(segmentToken.NextToken));
            }
            else
            {
                RangeVariable implicitRangeVariable = state.ImplicitRangeVariable;
                return(NodeFactory.CreateRangeVariableReferenceNode(implicitRangeVariable));
            }
        }
Beispiel #2
0
 /// <summary>
 /// Try to bind an inner path token as a function call. Used for bound functions without parameters
 /// that parse as inner path tokens syntactically
 /// </summary>
 /// <param name="innerPathToken">the end path token to bind</param>
 /// <param name="parent">the parent node to this end path token.</param>
 /// <param name="boundFunction">a single value function call node representing the function call, if it exists</param>
 /// <returns>true if we found a function for this token, false otherwise.</returns>
 internal bool TryBindInnerPathAsFunctionCall(InnerPathToken innerPathToken, QueryNode parent, out QueryNode boundFunction)
 {
     return(this.TryBindIdentifier(innerPathToken.Identifier, null, parent, state, out boundFunction));
 }
Beispiel #3
0
        /// <summary>
        /// Binds an InnerPathToken.
        /// </summary>
        /// <param name="token">Token to bind.</param>
        /// <returns>Either a SingleNavigationNode, CollectionNavigationNode, SinglePropertyAccessNode (complex),
        /// or CollectionPropertyAccessNode (primitive or complex) that is the metadata-bound version of the given token.</returns>
        protected virtual QueryNode BindInnerPathSegment(InnerPathToken token)
        {
            InnerPathTokenBinder innerPathTokenBinder = new InnerPathTokenBinder(this.Bind, this.BindingState);

            return(innerPathTokenBinder.BindInnerPathSegment(token));
        }
Beispiel #4
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>
        /// <returns>The bound node.</returns>
        internal QueryNode BindInnerPathSegment(InnerPathToken segmentToken)
        {
            FunctionCallBinder functionCallBinder = new FunctionCallBinder(this.bindMethod, state);

            // 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, 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, this.Resolver);

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

                if (singleValueParent.TypeReference != null && !singleValueParent.TypeReference.Definition.IsOpen())
                {
                    throw ExceptionUtil.CreatePropertyNotFoundException(segmentToken.Identifier, parent.GetEdmTypeReference().FullName());
                }

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

            IEdmStructuralProperty structuralProperty = property as IEdmStructuralProperty;

            if (property.Type.IsComplex())
            {
                // Generate a segment to parsed segments for the parsed token
                state.ParsedSegments.Add(new PropertySegment(structuralProperty));
                return(new SingleComplexNode(singleValueParent as SingleResourceNode, property));
            }
            else if (property.Type.IsPrimitive())
            {
                return(new SingleValuePropertyAccessNode(singleValueParent, property));
            }

            // Note - this means nonentity collection (primitive or complex)
            if (property.Type.IsNonEntityCollectionType())
            {
                if (property.Type.IsStructuredCollectionType())
                {
                    // Generate a segment to parsed segments for the parsed token
                    state.ParsedSegments.Add(new PropertySegment(structuralProperty));
                    return(new CollectionComplexNode(singleValueParent as SingleResourceNode, property));
                }

                return(new CollectionPropertyAccessNode(singleValueParent, property));
            }

            IEdmNavigationProperty navigationProperty = property as IEdmNavigationProperty;

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

            SingleResourceNode parentResource = EnsureParentIsResourceForNavProp(singleValueParent);

            IEdmNavigationSource navigationSource;
            QueryNode            node = GetNavigationNode(navigationProperty, parentResource, segmentToken.NamedValues, state,
                                                          new KeyBinder(this.bindMethod), out navigationSource);

            // Generate a segment to parsed segments for the parsed token
            state.ParsedSegments.Add(new NavigationPropertySegment(navigationProperty, navigationSource));

            return(node);
        }
 /// <summary>
 /// Visits a InnerPathToken
 /// </summary>
 /// <param name="tokenIn">The InnerPathToken to bind</param>
 /// <returns>A SingleValueNode or SingleEntityNode bound to this InnerPathToken</returns>
 public virtual T Visit(InnerPathToken tokenIn)
 {
     throw new NotImplementedException();
 }