Example #1
0
        /// <summary>
        /// add a new expandTermToken into an exisiting token, adding any additional levels and trees along the way.
        /// </summary>
        /// <param name="existingToken">the exisiting (already expanded) token</param>
        /// <param name="newToken">the new (already expanded) token</param>
        /// <returns>the combined token, or, if the two are mutually exclusive, the same tokens</returns>
        public static ExpandTermToken CombineTerms(ExpandTermToken existingToken, ExpandTermToken newToken)
        {
            Debug.Assert(new PathSegmentTokenEqualityComparer().Equals(existingToken.PathToNavProp, newToken.PathToNavProp), "Paths should be equal.");

            List <ExpandTermToken> childNodes = CombineChildNodes(existingToken, newToken).ToList();

            return(new ExpandTermToken(
                       existingToken.PathToNavProp,
                       existingToken.FilterOption,
                       existingToken.OrderByOption,
                       existingToken.TopOption,
                       existingToken.SkipOption,
                       existingToken.InlineCountOption,
                       existingToken.SelectOption,
                       new ExpandToken(childNodes)));
        }
Example #2
0
        /// <summary>
        /// Combine the child nodes of twoExpandTermTokens into one list of tokens
        /// </summary>
        /// <param name="existingToken">the existing token to to</param>
        /// <param name="newToken">the new token containing terms to add</param>
        /// <returns>a combined list of the all child nodes of the two tokens.</returns>
        public static IEnumerable <ExpandTermToken> CombineChildNodes(ExpandTermToken existingToken, ExpandTermToken newToken)
        {
            if (existingToken.ExpandOption == null && newToken.ExpandOption == null)
            {
                return(new List <ExpandTermToken>());
            }

            var childNodes = new Dictionary <PathSegmentToken, ExpandTermToken>(new PathSegmentTokenEqualityComparer());

            if (existingToken.ExpandOption != null)
            {
                AddChildOptionsToDictionary(existingToken, childNodes);
            }

            if (newToken.ExpandOption != null)
            {
                AddChildOptionsToDictionary(newToken, childNodes);
            }

            return(childNodes.Values);
        }
Example #3
0
        /// <summary>
        /// Generate a SubExpand based on the current nav property and the curren token
        /// </summary>
        /// <param name="currentNavProp">the current navigation property</param>
        /// <param name="tokenIn">the current token</param>
        /// <returns>a new SelectExpand clause bound to the current token and nav prop</returns>
        protected override SelectExpandClause GenerateSubExpand(IEdmNavigationProperty currentNavProp, ExpandTermToken tokenIn)
        {
            Debug.Assert(tokenIn.SelectOption == null, "Should not have select on individual expand items for this binder, because the V3 syntax does not support selects within the $expand clause.");
            ExpandBinder nextLevelBinder = new NonOptionExpandBinder(this.Configuration, currentNavProp.ToEntityType(), this.EntitySet != null ? this.EntitySet.FindNavigationTarget(currentNavProp) : null);

            return(nextLevelBinder.Bind(tokenIn.ExpandOption));
        }
Example #4
0
        /// <summary>
        /// Generate an expand item based on an ExpandTermToken
        /// </summary>
        /// <param name="tokenIn">the expandTerm token to visit</param>
        /// <returns>the expand item for this expand term token.</returns>
        private ExpandedNavigationSelectItem GenerateExpandItem(ExpandTermToken tokenIn)
        {
            ExceptionUtils.CheckArgumentNotNull(tokenIn, "tokenIn");

            // ensure that we're always dealing with a normalized tree
            if (tokenIn.PathToNavProp.NextToken != null && !tokenIn.PathToNavProp.IsNamespaceOrContainerQualified())
            {
                throw new ODataException(ODataErrorStrings.ExpandItemBinder_TraversingANonNormalizedTree);
            }

            PathSegmentToken        currentToken           = tokenIn.PathToNavProp;
            IEdmEntityType          currentLevelEntityType = this.entityType;
            List <ODataPathSegment> pathSoFar         = new List <ODataPathSegment>();
            PathSegmentToken        firstNonTypeToken = currentToken;

            if (currentToken.IsNamespaceOrContainerQualified())
            {
                pathSoFar.AddRange(SelectExpandPathBinder.FollowTypeSegments(currentToken, this.Model, this.Settings.SelectExpandLimit, ref currentLevelEntityType, out firstNonTypeToken));
            }

            IEdmProperty edmProperty = currentLevelEntityType.FindProperty(firstNonTypeToken.Identifier);

            if (edmProperty == null)
            {
                throw new ODataException(ODataErrorStrings.MetadataBinder_PropertyNotDeclared(currentLevelEntityType.FullName(), currentToken.Identifier));
            }

            IEdmNavigationProperty currentNavProp = edmProperty as IEdmNavigationProperty;

            if (currentNavProp == null)
            {
                // the server allowed non-navigation, non-stream properties to be expanded, but then ignored them.
                if (this.Settings.UseWcfDataServicesServerBehavior && !edmProperty.Type.IsStream())
                {
                    return(null);
                }

                throw new ODataException(ODataErrorStrings.ExpandItemBinder_PropertyIsNotANavigationProperty(currentToken.Identifier, currentLevelEntityType.FullName()));
            }

            pathSoFar.Add(new NavigationPropertySegment(currentNavProp, /*entitySet*/ null));
            ODataExpandPath pathToNavProp = new ODataExpandPath(pathSoFar);

            SelectExpandClause subSelectExpand;

            if (tokenIn.ExpandOption != null)
            {
                subSelectExpand = this.GenerateSubExpand(currentNavProp, tokenIn);
            }
            else
            {
                subSelectExpand = BuildDefaultSubExpand();
            }

            subSelectExpand = this.DecorateExpandWithSelect(subSelectExpand, currentNavProp, tokenIn.SelectOption);

            IEdmEntitySet targetEntitySet = null;

            if (this.entitySet != null)
            {
                targetEntitySet = this.entitySet.FindNavigationTarget(currentNavProp);
            }

            // call MetadataBinder to build the filter clause
            FilterClause filterOption = null;

            if (tokenIn.FilterOption != null)
            {
                MetadataBinder binder       = this.BuildNewMetadataBinder(targetEntitySet);
                FilterBinder   filterBinder = new FilterBinder(binder.Bind, binder.BindingState);
                filterOption = filterBinder.BindFilter(tokenIn.FilterOption);
            }

            // call MetadataBinder again to build the orderby clause
            OrderByClause orderbyOption = null;

            if (tokenIn.OrderByOption != null)
            {
                MetadataBinder binder        = this.BuildNewMetadataBinder(targetEntitySet);
                OrderByBinder  orderByBinder = new OrderByBinder(binder.Bind);
                orderbyOption = orderByBinder.BindOrderBy(binder.BindingState, new OrderByToken[] { tokenIn.OrderByOption });
            }

            return(new ExpandedNavigationSelectItem(pathToNavProp, targetEntitySet, filterOption, orderbyOption, tokenIn.TopOption, tokenIn.SkipOption, tokenIn.InlineCountOption, subSelectExpand));
        }
Example #5
0
 /// <summary>
 /// Generate a SubExpand based on the current nav property and the curren token
 /// </summary>
 /// <param name="currentNavProp">the current navigation property</param>
 /// <param name="tokenIn">the current token</param>
 /// <returns>a new SelectExpand clause bound to the current token and nav prop</returns>
 protected abstract SelectExpandClause GenerateSubExpand(IEdmNavigationProperty currentNavProp, ExpandTermToken tokenIn);
Example #6
0
        /// <summary>
        /// Expand all the PathTokens in a particular term into their own separate terms.
        /// </summary>
        /// <param name="termToExpand">the term to expand</param>
        /// <returns>a new ExpandTermToken with each PathToken at its own level.</returns>
        public static ExpandTermToken BuildSubExpandTree(ExpandTermToken termToExpand)
        {
            // walk up the path tree on the property token, adding new expand clauses for each level
            if (termToExpand.PathToNavProp.NextToken == null)
            {
                return(termToExpand);
            }

            PathSegmentToken currentProperty = termToExpand.PathToNavProp;

            // if we find a type token, then the current property becomes a path instead,
            // so that we can follow the chain of derived types from the base.
            // the path can only consist of NavProps or TypeSegments, we can
            // simply walk the tree of the current property until we find a non
            // type segment, then break its next link, then return the new path chain which
            // becomes our current property
            PathSegmentToken currentToken = currentProperty;

            while (currentToken.IsNamespaceOrContainerQualified())
            {
                currentToken = currentToken.NextToken;
                if (currentToken == null)
                {
                    throw new ODataException(ODataErrorStrings.ExpandTreeNormalizer_NonPathInPropertyChain);
                }
            }

            // get a pointer to the next property so that we can continue down the list.
            PathSegmentToken nextProperty = currentToken.NextToken;

            // chop off the next pointer to end this chain.
            currentToken.SetNextToken(null);

            ExpandToken subExpand;

            if (nextProperty != null)
            {
                var subExpandTermToken = new ExpandTermToken(
                    nextProperty,
                    termToExpand.FilterOption,
                    termToExpand.OrderByOption,
                    termToExpand.TopOption,
                    termToExpand.SkipOption,
                    termToExpand.InlineCountOption,
                    termToExpand.SelectOption,
                    /*expandOption*/ null);
                ExpandTermToken subExpandToken = BuildSubExpandTree(subExpandTermToken);
                subExpand = new ExpandToken(new[] { subExpandToken });
            }
            else
            {
                subExpand = new ExpandToken(new ExpandTermToken[0]);
            }

            return(new ExpandTermToken(
                       currentProperty,
                       termToExpand.FilterOption,
                       termToExpand.OrderByOption,
                       termToExpand.TopOption,
                       termToExpand.SkipOption,
                       termToExpand.InlineCountOption,
                       termToExpand.SelectOption,
                       subExpand));
        }
Example #7
0
        /// <summary>
        /// Adds the expand token to the dictionary or combines it with an existing  or combines it with another existing token with an equivalent path.
        /// </summary>
        /// <param name="combinedTerms">The combined terms dictionary.</param>
        /// <param name="expandedTerm">The expanded term to add or combine.</param>
        private static void AddOrCombine(IDictionary <PathSegmentToken, ExpandTermToken> combinedTerms, ExpandTermToken expandedTerm)
        {
            ExpandTermToken existingTerm;

            if (combinedTerms.TryGetValue(expandedTerm.PathToNavProp, out existingTerm))
            {
                combinedTerms[expandedTerm.PathToNavProp] = CombineTerms(expandedTerm, existingTerm);
            }
            else
            {
                combinedTerms.Add(expandedTerm.PathToNavProp, expandedTerm);
            }
        }
Example #8
0
 /// <summary>
 /// Visits an ExpandTermToken
 /// </summary>
 /// <param name="tokenIn">The ExpandTermToken to visit</param>
 /// <returns>A QueryNode bound to this ExpandTermToken</returns>
 public virtual T Visit(ExpandTermToken tokenIn)
 {
     throw new NotImplementedException();
 }
Example #9
0
        /// <summary>
        /// Generate a SubExpand based on the current nav property and the curren token
        /// </summary>
        /// <param name="currentNavProp">the current navigation property</param>
        /// <param name="tokenIn">the current token</param>
        /// <returns>a new SelectExpand clause bound to the current token and nav prop</returns>
        protected override SelectExpandClause GenerateSubExpand(IEdmNavigationProperty currentNavProp, ExpandTermToken tokenIn)
        {
            ExpandBinder nextLevelBinder = new ExpandOptionExpandBinder(this.Configuration, currentNavProp.ToEntityType(), this.EntitySet != null ? this.EntitySet.FindNavigationTarget(currentNavProp) : null);

            return(nextLevelBinder.Bind(tokenIn.ExpandOption));
        }