示例#1
0
        /// <summary>
        /// Binds a LambdaToken to metadata.
        /// </summary>
        /// <param name="lambdaToken">Token to bind.</param>
        /// <param name="state">Object to hold the state of binding.</param>
        /// <returns>A metadata bound any or all node.</returns>
        internal LambdaNode BindLambdaToken(LambdaToken lambdaToken, BindingState state)
        {
            ExceptionUtils.CheckArgumentNotNull(lambdaToken, "LambdaToken");
            ExceptionUtils.CheckArgumentNotNull(state, "state");

            // Start by binding the parent token
            CollectionNode parent        = this.BindParentToken(lambdaToken.Parent);
            RangeVariable  rangeVariable = null;

            // Add the lambda variable to the stack
            if (lambdaToken.Parameter != null)
            {
                rangeVariable = NodeFactory.CreateParameterNode(lambdaToken.Parameter, parent);
                state.RangeVariables.Push(rangeVariable);
            }

            // Bind the expression
            SingleValueNode expression = this.BindExpressionToken(lambdaToken.Expression);

            // Create the node
            LambdaNode lambdaNode = NodeFactory.CreateLambdaNode(state, parent, expression, rangeVariable, lambdaToken.Kind);

            // Remove the lambda variable as it is now out of scope
            if (rangeVariable != null)
            {
                state.RangeVariables.Pop();
            }

            return(lambdaNode);
        }
示例#2
0
        /// <summary>
        /// Creates an AnyNode or an AllNode from the given
        /// </summary>
        /// <param name="state">State of binding.</param>
        /// <param name="parent">Parent node to the lambda.</param>
        /// <param name="lambdaExpression">Bound Lambda expression.</param>
        /// <param name="newRangeVariable">The new range variable being added by this lambda node.</param>
        /// <param name="queryTokenKind">Token kind.</param>
        /// <returns>A new LambdaNode bound to metadata.</returns>
        internal static LambdaNode CreateLambdaNode(
            BindingState state,
            CollectionNode parent,
            SingleValueNode lambdaExpression,
            RangeVariable newRangeVariable,
            QueryTokenKind queryTokenKind)
        {
            LambdaNode lambdaNode;

            if (queryTokenKind == QueryTokenKind.Any)
            {
                lambdaNode = new AnyNode(new Collection <RangeVariable>(state.RangeVariables.ToList()), newRangeVariable)
                {
                    Body   = lambdaExpression,
                    Source = parent,
                };
            }
            else
            {
                Debug.Assert(queryTokenKind == QueryTokenKind.All, "LambdaQueryNodes must be Any or All only.");
                lambdaNode = new AllNode(new Collection <RangeVariable>(state.RangeVariables.ToList()), newRangeVariable)
                {
                    Body   = lambdaExpression,
                    Source = parent,
                };
            }

            return(lambdaNode);
        }
示例#3
0
        /// <summary>
        /// Creates a <see cref="FilterClause"/>.
        /// </summary>
        /// <param name="expression">The filter expression - this should evaluate to a single boolean value. Cannot be null.</param>
        /// <param name="rangeVariable">The parameter for the expression which represents a single value from the collection. Cannot be null.</param>
        /// <exception cref="System.ArgumentNullException">Throws if the input expression or rangeVariable is null.</exception>
        public FilterClause(SingleValueNode expression, RangeVariable rangeVariable)
        {
            ExceptionUtils.CheckArgumentNotNull(expression, "expression");
            ExceptionUtils.CheckArgumentNotNull(rangeVariable, "parameter");

            this.expression    = expression;
            this.rangeVariable = rangeVariable;
        }
示例#4
0
        /// <summary>
        /// Creates an <see cref="OrderByClause"/>.
        /// </summary>
        /// <param name="thenBy">The next orderby to perform after performing this orderby, can be null in the case of only a single orderby expression.</param>
        /// <param name="expression">The order-by expression. Cannot be null.</param>
        /// <param name="direction">The direction to order.</param>
        /// <param name="rangeVariable">The rangeVariable for the expression which represents a single value from the collection we iterate over. </param>
        /// <exception cref="System.ArgumentNullException">Throws if the input expression or rangeVariable is null.</exception>
        public OrderByClause(OrderByClause thenBy, SingleValueNode expression, OrderByDirection direction, RangeVariable rangeVariable)
        {
            ExceptionUtils.CheckArgumentNotNull(expression, "expression");
            ExceptionUtils.CheckArgumentNotNull(rangeVariable, "parameter");

            this.thenBy        = thenBy;
            this.expression    = expression;
            this.direction     = direction;
            this.rangeVariable = rangeVariable;
        }
示例#5
0
 /// <summary>
 /// Creates a RangeVariableReferenceNode for a given range variable
 /// </summary>
 /// <param name="rangeVariable">Name of the rangeVariable.</param>
 /// <returns>A new SingleValueNode (either a Resource or NonResource RangeVariableReferenceNode.</returns>
 internal static SingleValueNode CreateRangeVariableReferenceNode(RangeVariable rangeVariable)
 {
     if (rangeVariable.Kind == RangeVariableKind.NonResource)
     {
         return(new NonResourceRangeVariableReferenceNode(rangeVariable.Name, (NonResourceRangeVariable)rangeVariable));
     }
     else
     {
         ResourceRangeVariable resourceRangeVariable = (ResourceRangeVariable)rangeVariable;
         return(new ResourceRangeVariableReferenceNode(resourceRangeVariable.Name, resourceRangeVariable));
     }
 }
示例#6
0
        /// <summary>
        /// Binds a parameter token.
        /// </summary>
        /// <param name="rangeVariableToken">The parameter token to bind.</param>
        /// <param name="state">The state of metadata binding.</param>
        /// <returns>The bound query node.</returns>
        internal static SingleValueNode BindRangeVariableToken(RangeVariableToken rangeVariableToken, BindingState state)
        {
            ExceptionUtils.CheckArgumentNotNull(rangeVariableToken, "rangeVariableToken");

            RangeVariable rangeVariable = state.RangeVariables.SingleOrDefault(p => p.Name == rangeVariableToken.Name);

            if (rangeVariable == null)
            {
                throw new ODataException(ODataErrorStrings.MetadataBinder_ParameterNotInScope(rangeVariableToken.Name));
            }

            return(NodeFactory.CreateRangeVariableReferenceNode(rangeVariable));
        }
示例#7
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>
        /// <returns>A SingleValueQueryNode that is the parent node of the <paramref name="segmentToken"/>.</returns>
        private QueryNode DetermineParentNode(EndPathToken segmentToken)
        {
            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));
            }
        }
        private static BindingState CreateBindingState(ODataUriParserConfiguration config,
                                                       IEdmNavigationSource resourcePathNavigationSource, IEdmNavigationSource targetNavigationSource,
                                                       IEdmTypeReference elementType, HashSet <EndPathToken> generatedProperties = null,
                                                       bool collapsed = false)
        {
            if (targetNavigationSource == null && elementType == null)
            {
                return(null);
            }

            // For example if we have https://url/Books?$expand=Authors($filter=Name eq $it/Name)
            // $filter=Name will reference Authors(the expanded entity).
            // $it/Name will reference Books(the resource identified by the path).
            // The BindingState ImplicitRangeVariable property will store the $it that references the expanded/selected item (The Implicit Range Variable).
            // We add to the Stack, the $it that references the resource identified by the path (The Explicit Range Variable).

            BindingState state = new BindingState(config)
            {
                ImplicitRangeVariable =
                    NodeFactory.CreateImplicitRangeVariable(elementType != null ? elementType :
                                                            targetNavigationSource.EntityType().ToTypeReference(), targetNavigationSource)
            };

            state.AggregatedPropertyNames      = generatedProperties;
            state.IsCollapsed                  = collapsed;
            state.ResourcePathNavigationSource = resourcePathNavigationSource;

            if (resourcePathNavigationSource != null)
            {
                // This $it rangeVariable will be added the Stack.
                // We are adding a rangeVariable whose navigationSource is the resource path entity set.
                // ODATA spec: Example 106 http://docs.oasis-open.org/odata/odata/v4.01/csprd05/part2-url-conventions/odata-v4.01-csprd05-part2-url-conventions.html#sec_it
                RangeVariable explicitRangeVariable = NodeFactory.CreateImplicitRangeVariable(
                    resourcePathNavigationSource.EntityType().ToTypeReference(), resourcePathNavigationSource);
                state.RangeVariables.Push(explicitRangeVariable);
            }

            // Create $this rangeVariable and add it to the Stack.
            RangeVariable dollarThisRangeVariable = NodeFactory.CreateDollarThisRangeVariable(
                elementType != null ? elementType : targetNavigationSource.EntityType().ToTypeReference(), targetNavigationSource);

            state.RangeVariables.Push(dollarThisRangeVariable);

            return(state);
        }
示例#9
0
        /// <summary>
        /// Build a segment representing $filter.
        /// </summary>
        /// <param name="expression">The filter expression - this should evaluate to a single boolean value.</param>
        /// <param name="rangeVariable">An expression that represents a single value from the collection.</param>
        /// <param name="navigationSource">The navigation source that this filter applies to.</param>
        /// <exception cref="System.ArgumentNullException">Throws if any input parameter is null.</exception>
        /// <remarks>$filter should not be applied on singletons or single entities.</remarks>
        public FilterSegment(SingleValueNode expression, RangeVariable rangeVariable, IEdmNavigationSource navigationSource)
        {
            ExceptionUtils.CheckArgumentNotNull(expression, "expression");
            ExceptionUtils.CheckArgumentNotNull(rangeVariable, "rangeVariable");
            ExceptionUtils.CheckArgumentNotNull(navigationSource, "navigationSource");

            this.Identifier   = UriQueryConstants.FilterSegment;
            this.SingleResult = false;
            this.TargetEdmNavigationSource = navigationSource;
            this.TargetKind    = RequestTargetKind.Resource;
            this.TargetEdmType = rangeVariable.TypeReference.Definition;

            this.expression    = expression;
            this.rangeVariable = rangeVariable;
            this.bindingType   = navigationSource.Type;

            NodeToStringBuilder nodeToStringBuilder = new NodeToStringBuilder();
            string expressionString = nodeToStringBuilder.TranslateNode(expression);

            this.literalText = UriQueryConstants.FilterSegment + ExpressionConstants.SymbolOpenParen + expressionString
                               + ExpressionConstants.SymbolClosedParen;
        }
示例#10
0
 /// <summary>
 /// Create a AnyNode
 /// </summary>
 /// <param name="parameters">The name of the parameter list.</param>
 /// <param name="currentRangeVariable">The name of the new range variable being added by this AnyNode</param>
 public AnyNode(Collection <RangeVariable> parameters, RangeVariable currentRangeVariable)
     : base(parameters, currentRangeVariable)
 {
 }
示例#11
0
 /// <summary>
 /// Create an AllNode
 /// </summary>
 /// <param name="rangeVariables">The name of the rangeVariables list.</param>
 /// <param name="currentRangeVariable">The new range variable being added by this all node</param>
 public AllNode(Collection <RangeVariable> rangeVariables, RangeVariable currentRangeVariable)
     : base(rangeVariables, currentRangeVariable)
 {
 }
示例#12
0
 /// <summary>
 /// Create a LambdaNode
 /// </summary>
 /// <param name="rangeVariables">The collection of rangeVariables in scope for this Any or All.</param>
 /// <param name="currentRangeVariable">The newest range variable added for by this Any or All.</param>
 protected LambdaNode(Collection <RangeVariable> rangeVariables, RangeVariable currentRangeVariable)
 {
     this.rangeVariables       = rangeVariables;
     this.currentRangeVariable = currentRangeVariable;
 }