コード例 #1
0
        private static bool TryBindAsOperation(PathSegmentToken pathToken, IEdmModel model, IEdmEntityType entityType, out ODataPathSegment segment)
        {
            Debug.Assert(pathToken != null, "pathToken != null");
            Debug.Assert(entityType != null, "bindingType != null");

            IEnumerable <IEdmFunctionImport> functionImports;
            var resolver = model as IODataUriParserModelExtensions;

            if (resolver != null)
            {
                functionImports = resolver.FindFunctionImportsByBindingParameterTypeHierarchy(entityType, pathToken.Identifier);
            }
            else
            {
                functionImports = model.FindFunctionImportsByBindingParameterTypeHierarchy(entityType, pathToken.Identifier);
            }

            List <IEdmFunctionImport> possibleFunctions = functionImports.ToList();

            if (possibleFunctions.Count <= 0)
            {
                segment = null;
                return(false);
            }

            segment = new OperationSegment(possibleFunctions, null /*entitySet*/);
            return(true);
        }
コード例 #2
0
        /// <summary>
        /// Build a segment from a token.
        /// </summary>
        /// <param name="tokenIn">the token to bind</param>
        /// <param name="model">The model.</param>
        /// <param name="entityType">the entity type of the current scope based on type segments.</param>
        /// <returns>The segment created from the token.</returns>
        public static ODataPathSegment ConvertNonTypeTokenToSegment(PathSegmentToken tokenIn, IEdmModel model, IEdmEntityType entityType)
        {
            ODataPathSegment nextSegment;

            if (TryBindAsDeclaredProperty(tokenIn, entityType, out nextSegment))
            {
                return(nextSegment);
            }

            // for open types, operations must be container-qualified, and because the token type indicates it was not a .-seperated identifier, we should not try to look up operations.
            if (!entityType.IsOpen || tokenIn.IsNamespaceOrContainerQualified())
            {
                if (TryBindAsOperation(tokenIn, model, entityType, out nextSegment))
                {
                    return(nextSegment);
                }
            }

            if (entityType.IsOpen)
            {
                return(new OpenPropertySegment(tokenIn.Identifier));
            }

            throw new ODataException(ODataErrorStrings.MetadataBinder_PropertyNotDeclared(entityType.FullName(), tokenIn.Identifier));
        }
コード例 #3
0
 /// <summary>
 /// Create an expand term using only the property and its subexpand/select
 /// </summary>
 /// <param name="pathToNavProp">the path to the navigation property for this expand term</param>
 /// <param name="selectOption">the sub select for this token</param>
 /// <param name="expandOption">the sub expand for this token</param>
 public ExpandTermToken(PathSegmentToken pathToNavProp, SelectToken selectOption, ExpandToken expandOption)
 {
     ExceptionUtils.CheckArgumentNotNull(pathToNavProp, "pathToNavigationProperty");
     this.pathToNavProp = pathToNavProp;
     this.filterOption  = null;
     this.orderByOption = null;
     this.topOption     = null;
     this.skipOption    = null;
     this.selectOption  = selectOption;
     this.expandOption  = expandOption;
 }
コード例 #4
0
        /// <summary>
        /// Create an expand term token
        /// </summary>
        /// <param name="pathToNavProp">the nav prop for this expand term</param>
        /// <param name="filterOption">the filter option for this expand term</param>
        /// <param name="orderByOption">the orderby option for this expand term</param>
        /// <param name="topOption">the top option for this expand term</param>
        /// <param name="skipOption">the skip option for this expand term</param>
        /// <param name="inlineCountOption">the inlineCountOption for this expand term</param>
        /// <param name="selectOption">the select option for this expand term</param>
        /// <param name="expandOption">the expand option for this expand term</param>
        public ExpandTermToken(PathSegmentToken pathToNavProp, QueryToken filterOption, OrderByToken orderByOption, long?topOption, long?skipOption, InlineCountKind?inlineCountOption, SelectToken selectOption, ExpandToken expandOption)
        {
            ExceptionUtils.CheckArgumentNotNull(pathToNavProp, "property");

            this.pathToNavProp     = pathToNavProp;
            this.filterOption      = filterOption;
            this.orderByOption     = orderByOption;
            this.topOption         = topOption;
            this.skipOption        = skipOption;
            this.inlineCountOption = inlineCountOption;
            this.selectOption      = selectOption;
            this.expandOption      = expandOption;
        }
コード例 #5
0
ファイル: ExpandTreeNormalizer.cs プロジェクト: tapika/swupd
        /// <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 InvertPaths(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.PathToNavProp.Accept(pathReverser);
                ExpandTermToken  newTerm      = new ExpandTermToken(reversedPath, term.FilterOption, term.OrderByOption, term.TopOption, term.SkipOption, term.InlineCountOption, term.SelectOption, term.ExpandOption);
                updatedTerms.Add(newTerm);
            }

            return(new ExpandToken(updatedTerms));
        }
コード例 #6
0
        /// <summary>
        /// Follow any type segments on the path, stopping at the first segment that isn't a type token.
        /// </summary>
        /// <param name="firstTypeToken">the first type segment</param>
        /// <param name="model">the model these types are contained in.</param>
        /// <param name="maxDepth">the maximum recursive depth</param>
        /// <param name="currentLevelEntityType">the top level entity type, will be overwritten with the last entity type in the chain</param>
        /// <param name="firstNonTypeToken">the first non type token in the path</param>
        /// <returns>A path with type segments added to it.</returns>
        public static IEnumerable <ODataPathSegment> FollowTypeSegments(PathSegmentToken firstTypeToken, IEdmModel model, int maxDepth, ref IEdmEntityType currentLevelEntityType, out PathSegmentToken firstNonTypeToken)
        {
            ExceptionUtils.CheckArgumentNotNull(firstTypeToken, "firstTypeToken");
            ExceptionUtils.CheckArgumentNotNull(model, "model");

            if (!firstTypeToken.IsNamespaceOrContainerQualified())
            {
                throw new ODataException(ODataErrorStrings.SelectExpandPathBinder_FollowNonTypeSegment(firstTypeToken.Identifier));
            }

            int index = 0;
            List <ODataPathSegment> pathToReturn = new List <ODataPathSegment>();
            PathSegmentToken        currentToken = firstTypeToken;

            while (currentToken.IsNamespaceOrContainerQualified() && currentToken.NextToken != null)
            {
                IEdmEntityType previousLevelEntityType = currentLevelEntityType;
                currentLevelEntityType = UriEdmHelpers.FindTypeFromModel(model, currentToken.Identifier) as IEdmEntityType;
                if (currentLevelEntityType == null)
                {
                    // TODO: fix this error message?
                    throw new ODataException(ODataErrorStrings.ExpandItemBinder_CannotFindType(currentToken.Identifier));
                }

                UriEdmHelpers.CheckRelatedTo(previousLevelEntityType, currentLevelEntityType);
                pathToReturn.Add(new TypeSegment(currentLevelEntityType, /*entitySet*/ null));

                index++;
                currentToken = currentToken.NextToken;

                if (index >= maxDepth)
                {
                    throw new ODataException(ODataErrorStrings.ExpandItemBinder_PathTooDeep);
                }
            }

            firstNonTypeToken = currentToken;

            return(pathToReturn);
        }
コード例 #7
0
        /// <summary>
        /// Build a wildcard selection item
        /// </summary>
        /// <param name="tokenIn">the token to bind to a wildcard</param>
        /// <param name="model">the model to search for this wildcard</param>
        /// <param name="item">the new wildcard selection item, if we found one</param>
        /// <returns>true if we successfully bound to a wildcard, false otherwise</returns>
        public static bool TryBindAsWildcard(PathSegmentToken tokenIn, IEdmModel model, out SelectItem item)
        {
            bool isTypeToken = tokenIn.IsNamespaceOrContainerQualified();
            bool wildcard    = tokenIn.Identifier.EndsWith("*", StringComparison.Ordinal);

            IEdmEntityContainer container;

            if (isTypeToken && wildcard && UriEdmHelpers.TryGetEntityContainer(tokenIn.Identifier.Substring(0, tokenIn.Identifier.LastIndexOf('.')), model, out container))
            {
                item = new ContainerQualifiedWildcardSelectItem(container);
                return(true);
            }

            if (tokenIn.Identifier == "*")
            {
                item = new WildcardSelectItem();
                return(true);
            }

            item = null;
            return(false);
        }
コード例 #8
0
        private static bool TryBindAsDeclaredProperty(PathSegmentToken tokenIn, IEdmEntityType entityType, out ODataPathSegment segment)
        {
            IEdmProperty prop = entityType.FindProperty(tokenIn.Identifier);

            if (prop == null)
            {
                segment = null;
                return(false);
            }

            if (prop.PropertyKind == EdmPropertyKind.Structural)
            {
                segment = new PropertySegment((IEdmStructuralProperty)prop);
                return(true);
            }

            if (prop.PropertyKind == EdmPropertyKind.Navigation)
            {
                segment = new NavigationPropertySegment((IEdmNavigationProperty)prop, null /*TODO set*/);
                return(true);
            }

            throw new ODataException(ODataErrorStrings.SelectExpandBinder_UnknownPropertyType(prop.Name));
        }
コード例 #9
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));
        }
コード例 #10
0
 /// <summary>
 /// internal setter for the next token.
 /// </summary>
 /// <param name="nextTokenIn">the next token to set.</param>
 internal void SetNextToken(PathSegmentToken nextTokenIn)
 {
     DebugUtils.CheckNoExternalCallers();
     this.nextToken = nextTokenIn;
 }
コード例 #11
0
 /// <summary>
 /// build this segment token using the next token
 /// </summary>
 /// <param name="nextToken">the next token in the path</param>
 protected PathSegmentToken(PathSegmentToken nextToken)
 {
     this.nextToken = nextToken;
 }
コード例 #12
0
ファイル: ExpandTreeNormalizer.cs プロジェクト: tapika/swupd
        /// <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));
        }
コード例 #13
0
ファイル: NonSystemToken.cs プロジェクト: tapika/swupd
        /// <summary>
        /// Build a NonSystemToken
        /// </summary>
        /// <param name="identifier">the identifier of this token</param>
        /// <param name="namedValues">a list of named values for this token</param>
        /// <param name="nextToken">the next token in the path</param>
        public NonSystemToken(string identifier, IEnumerable <NamedValue> namedValues, PathSegmentToken nextToken)
            : base(nextToken)
        {
            ExceptionUtils.CheckArgumentNotNull(identifier, "identifier");

            this.identifier  = identifier;
            this.namedValues = namedValues;
        }
コード例 #14
0
ファイル: SystemToken.cs プロジェクト: tapika/swupd
 /// <summary>
 /// Build a new System Token
 /// </summary>
 /// <param name="identifier">the identifier for this token.</param>
 /// <param name="nextToken">the next token in the path</param>
 public SystemToken(string identifier, PathSegmentToken nextToken)
     : base(nextToken)
 {
     ExceptionUtils.CheckArgumentNotNull(identifier, "identifier");
     this.identifier = identifier;
 }