/// <summary>
        /// Invert the all of the paths in an expandToken, such that they are now in the same order as they are present in the
        /// base url
        /// </summary>
        /// <param name="treeToInvert">the tree to invert paths on</param>
        /// <returns>a new tree with all of its paths inverted</returns>
        public ExpandToken NormalizePaths(ExpandToken treeToInvert)
        {
            // iterate through each expand term token, and reverse the tree in its path property
            List <ExpandTermToken> updatedTerms = new List <ExpandTermToken>();

            foreach (ExpandTermToken term in treeToInvert.ExpandTerms)
            {
                PathReverser     pathReverser = new PathReverser();
                PathSegmentToken reversedPath = term.PathToNavigationProp.Accept(pathReverser);

                // we also need to call the select token normalizer for this level to reverse the select paths
                SelectToken newSelectToken = term.SelectOption;
                if (term.SelectOption != null)
                {
                    newSelectToken = SelectTreeNormalizer.NormalizeSelectTree(term.SelectOption);
                }

                ExpandToken subExpandTree;
                if (term.ExpandOption != null)
                {
                    subExpandTree = this.NormalizePaths(term.ExpandOption);
                }
                else
                {
                    subExpandTree = null;
                }

                ExpandTermToken newTerm = new ExpandTermToken(reversedPath, term.FilterOption, term.OrderByOptions, term.TopOption, term.SkipOption, term.CountQueryOption, term.LevelsOption, term.SearchOption, newSelectToken, subExpandTree, term.ComputeOption);
                updatedTerms.Add(newTerm);
            }

            return(new ExpandToken(updatedTerms));
        }
        /// <summary>
        /// Add semantic meaning to a Select or Expand Token
        /// </summary>
        /// <param name="odataPathInfo">The path info from Uri path.</param>
        /// <param name="expandToken">the syntactically parsed expand token</param>
        /// <param name="selectToken">the syntactically parsed select token</param>
        /// <param name="configuration">The configuration to use for parsing.</param>
        /// <param name="state">The state of binding.</param>
        /// <returns>A select expand clause bound to metadata.</returns>
        public static SelectExpandClause Bind(
            ODataPathInfo odataPathInfo,
            ExpandToken expandToken,
            SelectToken selectToken,
            ODataUriParserConfiguration configuration,
            BindingState state)
        {
            ExpandToken normalizedExpand = ExpandTreeNormalizer.NormalizeExpandTree(expandToken);
            SelectToken normalizedSelect = SelectTreeNormalizer.NormalizeSelectTree(selectToken);

            SelectExpandBinder selectExpandBinder = new SelectExpandBinder(configuration, odataPathInfo, state);

            SelectExpandClause clause = selectExpandBinder.Bind(normalizedExpand, normalizedSelect);

            SelectExpandClauseFinisher.AddExplicitNavPropLinksWhereNecessary(clause);

            new ExpandDepthAndCountValidator(configuration.Settings.MaximumExpansionDepth, configuration.Settings.MaximumExpansionCount).Validate(clause);

            return(clause);
        }
        /// <summary>
        /// Invert the all of the paths in an expandToken, such that they are now in the same order as they are present in the
        /// base url
        /// </summary>
        /// <param name="treeToInvert">the tree to invert paths on</param>
        /// <returns>a new tree with all of its paths inverted</returns>
        public static ExpandToken NormalizePaths(ExpandToken treeToInvert)
        {
            if (treeToInvert != null)
            {
                // iterate through each expand term token, and reverse the tree in its path property
                foreach (ExpandTermToken term in treeToInvert.ExpandTerms)
                {
                    term.PathToProperty = term.PathToProperty.Reverse();

                    if (term.SelectOption != null)
                    {
                        term.SelectOption = SelectTreeNormalizer.NormalizeSelectTree(term.SelectOption);
                    }

                    if (term.ExpandOption != null)
                    {
                        term.ExpandOption = NormalizePaths(term.ExpandOption);
                    }
                }
            }

            return(treeToInvert);
        }