Example #1
0
 /// <summary>
 /// Create a new ODataUri. This contains the semantic meaning of the 
 /// entire uri.
 /// </summary>
 /// <param name="parameterAliasValueAccessor">The ParameterAliasValueAccessor.</param>
 /// <param name="path">The top level path for this uri.</param>
 /// <param name="customQueryOptions">Any custom query options for this uri. Can be null.</param>
 /// <param name="selectAndExpand">Any $select or $expand option for this uri. Can be null.</param>
 /// <param name="filter">Any $filter option for this uri. Can be null.</param>
 /// <param name="orderby">Any $orderby option for this uri. Can be null</param>
 /// <param name="search">Any $search option for this uri. Can be null</param>
 /// <param name="apply">Any $apply option for this uri. Can be null</param>
 /// <param name="skip">Any $skip option for this uri. Can be null.</param>
 /// <param name="top">Any $top option for this uri. Can be null.</param>
 /// <param name="queryCount">Any query $count option for this uri. Can be null.</param>
 internal ODataUri(
     ParameterAliasValueAccessor parameterAliasValueAccessor,
     ODataPath path,
     IEnumerable<QueryNode> customQueryOptions,
     SelectExpandClause selectAndExpand,
     FilterClause filter,
     OrderByClause orderby,
     SearchClause search,
     ApplyClause apply,
     long? skip,
     long? top,
     bool? queryCount)
 {
     this.ParameterAliasValueAccessor = parameterAliasValueAccessor;
     this.Path = path;
     this.CustomQueryOptions = new ReadOnlyCollection<QueryNode>(customQueryOptions.ToList());
     this.SelectAndExpand = selectAndExpand;
     this.Filter = filter;
     this.OrderBy = orderby;
     this.Search = search;
     this.Apply = apply;
     this.Skip = skip;
     this.Top = top;
     this.QueryCount = queryCount;
 }
Example #2
0
        /// <summary>
        /// Writes an OData entry.
        /// </summary>
        /// <param name="writer">The ODataWriter that will write the entry.</param>
        /// <param name="element">The item from the data store to write.</param>
        /// <param name="navigationSource">The navigation source in the model that the entry belongs to.</param>
        /// <param name="model">The data store model.</param>
        /// <param name="targetVersion">The OData version this segment is targeting.</param>
        /// <param name="selectExpandClause">The SelectExpandClause.</param>
        public static void WriteEntry(ODataWriter writer, object element, IEdmNavigationSource entitySource, ODataVersion targetVersion, SelectExpandClause selectExpandClause, Dictionary<string, string> incomingHeaders = null)
        {
            var entry = ODataObjectModelConverter.ConvertToODataEntry(element, entitySource, targetVersion);

            entry.ETag = Utility.GetETagValue(element);

            if (selectExpandClause != null && selectExpandClause.SelectedItems.OfType<PathSelectItem>().Any())
            {
                ExpandSelectItemHandler selectItemHandler = new ExpandSelectItemHandler(entry);
                foreach (var item in selectExpandClause.SelectedItems.OfType<PathSelectItem>())
                {
                    item.HandleWith(selectItemHandler);
                }

                entry = selectItemHandler.ProjectedEntry;
            }

            CustomizeEntry(incomingHeaders, entry);

            writer.WriteStart(entry);

            // gets all of the expandedItems, including ExpandedRefernceSelectItem and ExpandedNavigationItem
            var expandedItems = selectExpandClause == null ? null : selectExpandClause.SelectedItems.OfType<ExpandedReferenceSelectItem>();
            WriteNavigationLinks(writer, element, entry.ReadLink, entitySource, targetVersion, expandedItems);
            writer.WriteEnd();
        }
        private static void ValidateRestrictions(SelectExpandClause selectExpandClause, IEdmModel edmModel)
        {
            foreach (SelectItem selectItem in selectExpandClause.SelectedItems)
            {
                ExpandedNavigationSelectItem expandItem = selectItem as ExpandedNavigationSelectItem;
                if (expandItem != null)
                {
                    NavigationPropertySegment navigationSegment = (NavigationPropertySegment)expandItem.PathToNavigationProperty.LastSegment;
                    IEdmNavigationProperty navigationProperty = navigationSegment.NavigationProperty;
                    if (EdmLibHelpers.IsNotExpandable(navigationProperty, edmModel))
                    {
                        throw new ODataException(Error.Format(SRResources.NotExpandablePropertyUsedInExpand, navigationProperty.Name));
                    }
                    ValidateRestrictions(expandItem.SelectAndExpand, edmModel);
                }

                PathSelectItem pathSelectItem = selectItem as PathSelectItem;
                if (pathSelectItem != null)
                {
                    ODataPathSegment segment = pathSelectItem.SelectedPath.LastSegment;
                    NavigationPropertySegment navigationPropertySegment = segment as NavigationPropertySegment;
                    if (navigationPropertySegment != null)
                    {
                        IEdmNavigationProperty navigationProperty = navigationPropertySegment.NavigationProperty;
                        if (EdmLibHelpers.IsNotNavigable(navigationProperty, edmModel))
                        {
                            throw new ODataException(Error.Format(SRResources.NotNavigablePropertyUsedInNavigation, navigationProperty.Name));
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Recursively ensures that the maximum count/depth are not exceeded by walking the tree.
        /// </summary>
        /// <param name="expandTree">The expand tree to walk and validate.</param>
        /// <param name="currentDepth">The current depth of the tree walk.</param>
        private void EnsureMaximumCountAndDepthAreNotExceeded(SelectExpandClause expandTree, int currentDepth)
        {
            Debug.Assert(expandTree != null, "expandTree != null");
            if (currentDepth > this.maxDepth)
            {
                throw ExceptionUtil.CreateBadRequestError(ODataErrorStrings.UriParser_ExpandDepthExceeded(currentDepth, this.maxDepth));
            }

            foreach (ExpandedNavigationSelectItem expandItem in expandTree.SelectedItems.Where(I => I.GetType() == typeof(ExpandedNavigationSelectItem)))
            {
                this.currentCount++;
                if (this.currentCount > this.maxCount)
                {
                    throw ExceptionUtil.CreateBadRequestError(ODataErrorStrings.UriParser_ExpandCountExceeded(this.currentCount, this.maxCount));
                }

                this.EnsureMaximumCountAndDepthAreNotExceeded(expandItem.SelectAndExpand, currentDepth + 1);
            }

            this.currentCount += expandTree.SelectedItems.Where(I => I.GetType() == typeof(ExpandedReferenceSelectItem)).Count();
            if (this.currentCount > this.maxCount)
            {
                throw ExceptionUtil.CreateBadRequestError(ODataErrorStrings.UriParser_ExpandCountExceeded(this.currentCount, this.maxCount));
            }
        }
Example #5
0
        /// <summary>
        /// Constructs a new SelectBinder.
        /// </summary>
        /// <param name="model">The model used for binding.</param>
        /// <param name="edmType">The entity type that the $select is being applied to.</param>
        /// <param name="maxDepth">the maximum recursive depth.</param>
        /// <param name="expandClauseToDecorate">The already built expand clause to decorate</param>
       /// <param name="resolver">Resolver for uri parser.</param>
        public SelectBinder(IEdmModel model, IEdmStructuredType edmType, int maxDepth, SelectExpandClause expandClauseToDecorate, ODataUriResolver resolver = null)
        {
            ExceptionUtils.CheckArgumentNotNull(model, "tokenIn");
            ExceptionUtils.CheckArgumentNotNull(edmType, "entityType");

            this.visitor = new SelectPropertyVisitor(model, edmType, maxDepth, expandClauseToDecorate, resolver);
        }
 public void AllSelectedIsSetIfSelectIsEmpty()
 {
     var expandTree = new SelectExpandClause(new Collection<SelectItem>(), false);
     var binder = new SelectBinder(HardCodedTestModel.TestModel, HardCodedTestModel.GetPersonType(), 800, expandTree);
     var selectToken = new SelectToken(new List<PathSegmentToken>());
     binder.Bind(selectToken).AllSelected.Should().BeTrue();
 }
 private static void SnapResult(List<DeltaSnapshotEntry> results, object entry, IEdmNavigationSource entitySource, SelectExpandClause selectExpandClause, string parentId, string relationShip)
 {
     var oDataEntry = ODataObjectModelConverter.ConvertToODataEntry(entry, entitySource, ODataVersion.V4);
     results.Add(new DeltaSnapshotEntry(oDataEntry.Id.AbsoluteUri, parentId, relationShip));
     var expandedNavigationItems = selectExpandClause == null ? null : selectExpandClause.SelectedItems.OfType<ExpandedNavigationSelectItem>();
     SnapExpandedEntry(results, entry, entitySource, expandedNavigationItems, oDataEntry.Id.AbsoluteUri);
 }
 public static void SnapResults(List<DeltaSnapshotEntry> results, IEnumerable entries, IEdmNavigationSource entitySource, SelectExpandClause selectExpandClause, string parentId, string relationShip)
 {
     foreach (object entry in entries)
     {
         SnapResult(results, entry, entitySource, selectExpandClause, parentId, relationShip);
     }
 }
        /// <summary>
        /// Add any explicit nav prop links to a select expand clause as necessary.
        /// </summary>
        /// <param name="clause">the select expand clause to modify.</param>
        public static void AddExplicitNavPropLinksWhereNecessary(SelectExpandClause clause)
        {
            IEnumerable<SelectItem> selectItems = clause.SelectedItems;

            // make sure that there are already selects for this level, otherwise we change the select semantics.
            bool anyPathSelectItems = selectItems.Any(x => x is PathSelectItem);

            // if there are selects for this level, then we need to add nav prop select items for each
            // expanded nav prop
            IEnumerable<ODataSelectPath> selectedPaths = selectItems.OfType<PathSelectItem>().Select(item => item.SelectedPath);
            foreach (ExpandedNavigationSelectItem navigationSelect in selectItems.Where(I => I.GetType() == typeof(ExpandedNavigationSelectItem)))
            {
                if (anyPathSelectItems && !selectedPaths.Any(x => x.Equals(navigationSelect.PathToNavigationProperty.ToSelectPath())))
                {
                    clause.AddToSelectedItems(new PathSelectItem(navigationSelect.PathToNavigationProperty.ToSelectPath()));
                }

                AddExplicitNavPropLinksWhereNecessary(navigationSelect.SelectAndExpand);
            }

            foreach (ExpandedReferenceSelectItem navigationSelect in selectItems.Where(I => I.GetType() == typeof(ExpandedReferenceSelectItem)))
            {
                if (anyPathSelectItems && !selectedPaths.Any(x => x.Equals(navigationSelect.PathToNavigationProperty.ToSelectPath())))
                {
                    clause.AddToSelectedItems(new PathSelectItem(navigationSelect.PathToNavigationProperty.ToSelectPath()));
                }
            }
        }
        public void Ctor_ThatBuildsNestedContext_CopiesProperties()
        {
            // Arrange
            CustomersModelWithInheritance model = new CustomersModelWithInheritance();
            ODataSerializerContext context = new ODataSerializerContext
            {
                EntitySet = model.Customers,
                MetadataLevel = ODataMetadataLevel.FullMetadata,
                Model = model.Model,
                Path = new ODataPath(),
                Request = new HttpRequestMessage(),
                RootElementName = "somename",
                SelectExpandClause = new SelectExpandClause(new SelectItem[0], allSelected: true),
                SkipExpensiveAvailabilityChecks = true,
                Url = new UrlHelper()
            };
            EntityInstanceContext entity = new EntityInstanceContext { SerializerContext = context };
            SelectExpandClause selectExpand = new SelectExpandClause(new SelectItem[0], allSelected: true);
            IEdmNavigationProperty navProp = model.Customer.NavigationProperties().First();

            // Act
            ODataSerializerContext nestedContext = new ODataSerializerContext(entity, selectExpand, navProp);

            // Assert
            Assert.Equal(context.MetadataLevel, nestedContext.MetadataLevel);
            Assert.Same(context.Model, nestedContext.Model);
            Assert.Same(context.Path, nestedContext.Path);
            Assert.Same(context.Request, nestedContext.Request);
            Assert.Equal(context.RootElementName, nestedContext.RootElementName);
            Assert.Equal(context.SkipExpensiveAvailabilityChecks, nestedContext.SkipExpensiveAvailabilityChecks);
            Assert.Same(context.Url, nestedContext.Url);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="ODataSerializerContext"/> class.
        /// </summary>
        /// <param name="entity">The entity whose navigation property is being expanded.</param>
        /// <param name="selectExpandClause">The <see cref="SelectExpandClause"/> for the navigation property being expanded.</param>
        /// <param name="navigationProperty">The navigation property being expanded.</param>
        /// <remarks>This constructor is used to construct the serializer context for writing expanded properties.</remarks>
        public ODataSerializerContext(EntityInstanceContext entity, SelectExpandClause selectExpandClause, IEdmNavigationProperty navigationProperty)
        {
            if (entity == null)
            {
                throw Error.ArgumentNull("entity");
            }
            if (navigationProperty == null)
            {
                throw Error.ArgumentNull("navigationProperty");
            }

            ODataSerializerContext context = entity.SerializerContext;

            Request = context.Request;
            RequestContext = context.RequestContext;
            Url = context.Url;
            NavigationSource = context.NavigationSource;
            Model = context.Model;
            Path = context.Path;
            RootElementName = context.RootElementName;
            SkipExpensiveAvailabilityChecks = context.SkipExpensiveAvailabilityChecks;
            MetadataLevel = context.MetadataLevel;
            Items = context.Items;

            ExpandedEntity = entity;
            SelectExpandClause = selectExpandClause;
            NavigationProperty = navigationProperty;

            NavigationSource = context.NavigationSource.FindNavigationTarget(navigationProperty);
        }
Example #12
0
        /// <summary>Creates new root node for the projection tree.</summary>
        /// <param name="resourceSetWrapper">The resource set of the root level of the query.</param>
        /// <param name="orderingInfo">The ordering info for this node. null means no ordering to be applied.</param>
        /// <param name="filter">The filter for this node. null means no filter to be applied.</param>
        /// <param name="skipCount">Number of results to skip. null means no results to be skipped.</param>
        /// <param name="takeCount">Maximum number of results to return. null means return all available results.</param>
        /// <param name="maxResultsExpected">Maximum number of expected results. Hint that the provider should return
        /// at least maxResultsExpected + 1 results (if available).</param>
        /// <param name="expandPaths">The list of expanded paths.</param>
        /// <param name="baseResourceType">The resource type for all entities in this query.</param>
        /// <param name="selectExpandClause">The select expand clause for the current node from the URI Parser.</param>
        internal RootProjectionNode(
            ResourceSetWrapper resourceSetWrapper,
            OrderingInfo orderingInfo,
            Expression filter,
            int? skipCount,
            int? takeCount,
            int? maxResultsExpected,
            List<ExpandSegmentCollection> expandPaths,
            ResourceType baseResourceType,
            SelectExpandClause selectExpandClause)
            : base(
                String.Empty,
                null,
                null,
                resourceSetWrapper,
                orderingInfo,
                filter,
                skipCount,
                takeCount,
                maxResultsExpected,
                selectExpandClause)
        {
            Debug.Assert(baseResourceType != null, "baseResourceType != null");

            this.expandPaths = expandPaths;
            this.baseResourceType = baseResourceType;
        }
        public void NonSystemTokenTranslatedToSelectionItem()
        {
            var expandTree = new SelectExpandClause(new Collection<SelectItem>(), false);
            var binder = new SelectBinder(HardCodedTestModel.TestModel, HardCodedTestModel.GetPersonType(), 800, expandTree);
            var selectToken = new SelectToken(new List<PathSegmentToken>() { new NonSystemToken("Shoe", null, null) });

            binder.Bind(selectToken).SelectedItems.Single().ShouldBePathSelectionItem(new ODataPath(new PropertySegment(HardCodedTestModel.GetPersonShoeProp())));
        }
        public void Ctor_ForNestedContext_ThrowsArgumentNull_Entity()
        {
            SelectExpandClause selectExpand = new SelectExpandClause(new SelectItem[0], allSelected: true);
            IEdmNavigationProperty navProp = new Mock<IEdmNavigationProperty>().Object;

            Assert.ThrowsArgumentNull(
                () => new ODataSerializerContext(entity: null, selectExpandClause: selectExpand, navigationProperty: navProp), "entity");
        }
Example #15
0
 /// <summary>
 /// Build a property visitor to visit the select tree and decorate a SelectExpandClause
 /// </summary>
 /// <param name="model">The model used for binding.</param>
 /// <param name="edmType">The entity type that the $select is being applied to.</param>
 /// <param name="maxDepth">the maximum recursive depth.</param>
 /// <param name="expandClauseToDecorate">The already built expand clause to decorate</param>
 /// <param name="resolver">Resolver for uri parser.</param>
 public SelectPropertyVisitor(IEdmModel model, IEdmStructuredType edmType, int maxDepth, SelectExpandClause expandClauseToDecorate, ODataUriResolver resolver)
 {
     this.model = model;
     this.edmType = edmType;
     this.maxDepth = maxDepth;
     this.expandClauseToDecorate = expandClauseToDecorate;
     this.resolver = resolver ?? ODataUriResolver.Default;
 }
 public void SuccessfullyAddSelectionItems()
 {
     ODataSelectPath personNamePath = new ODataSelectPath(new PropertySegment(HardCodedTestModel.GetPersonNameProp()));
     ODataSelectPath personShoePath = new ODataSelectPath(new PropertySegment(HardCodedTestModel.GetPersonShoeProp()));
     var clause = new SelectExpandClause(new List<ExpandedNavigationSelectItem>(), false);
     clause.AddToSelectedItems(new PathSelectItem(personShoePath));
     clause.AddToSelectedItems(new PathSelectItem(personNamePath));
     clause.SelectedItems.Should().HaveCount(2).And.Contain(x => x is PathSelectItem && x.As<PathSelectItem>().SelectedPath == personNamePath).And.Contain(x => x is PathSelectItem && x.As<PathSelectItem>().SelectedPath == personShoePath);
 }
 internal SelectExpandQueryOption(
     string select,
     string expand,
     ODataQueryContext context,
     SelectExpandClause selectExpandClause)
     : this(select, expand, context)
 {
     _selectExpandClause = selectExpandClause;
 }
Example #18
0
 /// <summary>
 /// Handle first level entities, genreate the delta items which need to be write
 /// </summary>
 /// <param name="entries">Query results</param>
 /// <param name="entitySet">EntitySet</param>
 /// <param name="targetVersion">Target Version</param>
 /// <param name="selectExpandClause">Select and Expand Clause</param>
 private void GenerateDeltaItemsFromFeed(IEnumerable entries, IEdmNavigationSource entitySet, ODataVersion targetVersion, SelectExpandClause selectExpandClause)
 {
     foreach (var entry in entries)
     {
         // Handle single element in first level and their related navigation property
         GenerateDeltaItemFromEntry(entry, entitySet, targetVersion, selectExpandClause, string.Empty, string.Empty);
     }
     // Handle deleted element in first level
     GenerateDeltaItemsFromDeletedEntities(string.Empty, string.Empty);
 }
 public void ExistingWildcardPreemptsAnyNewPropertiesAdded()
 {
     var expandTree = new SelectExpandClause(new Collection<SelectItem>() 
                                 {
                                     new WildcardSelectItem()
                                 }, false);
     var binder = new SelectBinder(HardCodedTestModel.TestModel, HardCodedTestModel.GetPersonType(), 800, expandTree);
     var selectToken = new SelectToken(new List<PathSegmentToken>() { new NonSystemToken("Name", null, null) });
     binder.Bind(selectToken).SelectedItems.Single().ShouldBeWildcardSelectionItem();
 }
 public void ExpandedNavigationPropertiesAreNotAddedAsPathSelectionItemsIfSelectIsNotPopulated()
 {
     SelectExpandClause clause = new SelectExpandClause(new SelectItem[]
     {
         new ExpandedNavigationSelectItem(new ODataExpandPath(new NavigationPropertySegment(ModelBuildingHelpers.BuildValidNavigationProperty(), ModelBuildingHelpers.BuildValidEntitySet())), ModelBuildingHelpers.BuildValidEntitySet(), new SelectExpandClause(new List<SelectItem>(), false)), 
     },
     false /*allSelected*/);
     SelectExpandClauseFinisher.AddExplicitNavPropLinksWhereNecessary(clause);
     clause.SelectedItems.Should().HaveCount(1);
 }
        public void WildcardSelectionItemPreemptsStructuralProperties()
        {
            var expandTree = new SelectExpandClause(new Collection<SelectItem>() 
                                        {
                                            new PathSelectItem(new ODataSelectPath(new PropertySegment( HardCodedTestModel.GetPersonNameProp()))),
                                        }, false);
            var binder = new SelectBinder(HardCodedTestModel.TestModel, HardCodedTestModel.GetPersonType(), 800, expandTree);
            var selectToken = new SelectToken(new List<PathSegmentToken>() { new NonSystemToken("*", null, null) });

            binder.Bind(selectToken).SelectedItems.Single().ShouldBeWildcardSelectionItem();
        }
        /// <summary>
        /// Generate delta token and save (delta token, delta query) mapping
        /// </summary>
        /// <param name="query">Delta query</param>
        /// <returns>Delta token</returns>
        public static string GenerateDeltaToken(Uri query, IEnumerable entries, IEdmNavigationSource entitySource, SelectExpandClause selectExpandClause)
        {
            // TODO: Consider multiple threads here, may need add lock here.
            //       May need to optimize here, if $top/$skip/$count

            //var builder = new ODataAnnotationUriBuilder(baseUri);
            var deltaSnapshot = new DeltaSnapshot(query);
            SnapResults(deltaSnapshot.Entries, entries, entitySource, selectExpandClause, string.Empty, string.Empty);
            string deltaToken = deltaSnapshot.TimeStamp.Ticks.ToString(CultureInfo.InvariantCulture);
            DeltaTokenDic[deltaToken] = deltaSnapshot;
            return deltaToken;
        }
 public void ExpandedNavigationPropertiesAreImplicitlyAddedAsPathSelectionItemsIfSelectIsPopulated()
 {
     IEdmNavigationProperty navigationProperty = ModelBuildingHelpers.BuildValidNavigationProperty();
     SelectExpandClause clause = new SelectExpandClause(new SelectItem[]
     {
         new PathSelectItem(new ODataSelectPath(new PropertySegment(ModelBuildingHelpers.BuildValidPrimitiveProperty()))),
         new ExpandedNavigationSelectItem(new ODataExpandPath(new NavigationPropertySegment(navigationProperty, ModelBuildingHelpers.BuildValidEntitySet())), ModelBuildingHelpers.BuildValidEntitySet(), new SelectExpandClause(new List<SelectItem>(), false)), 
     },
     false /*allSelected*/);
     SelectExpandClauseFinisher.AddExplicitNavPropLinksWhereNecessary(clause);
     clause.SelectedItems.Should().HaveCount(3)
         .And.Contain(x => x is PathSelectItem && x.As<PathSelectItem>().SelectedPath.LastSegment is NavigationPropertySegment && x.As<PathSelectItem>().SelectedPath.LastSegment.As<NavigationPropertySegment>().NavigationProperty.Name == navigationProperty.Name);
 }
Example #24
0
        /// <summary>
        /// Creates a new instance of the <see cref="SelectExpandNode"/> class describing the set of structural properties,
        /// navigation properties, and actions to select and expand for the given <paramref name="selectExpandClause"/>.
        /// </summary>
        /// <param name="selectExpandClause">The parsed $select and $expand query options.</param>
        /// <param name="entityType">The entity type of the entry that would be written.</param>
        /// <param name="model">The <see cref="IEdmModel"/> that contains the given entity type.</param>
        public SelectExpandNode(SelectExpandClause selectExpandClause, IEdmEntityType entityType, IEdmModel model)
            : this()
        {
            if (entityType == null)
            {
                throw Error.ArgumentNull("entityType");
            }
            if (model == null)
            {
                throw Error.ArgumentNull("model");
            }

            HashSet<IEdmStructuralProperty> allStructuralProperties = new HashSet<IEdmStructuralProperty>(entityType.StructuralProperties());
            HashSet<IEdmNavigationProperty> allNavigationProperties = new HashSet<IEdmNavigationProperty>(entityType.NavigationProperties());
            HashSet<IEdmAction> allActions = new HashSet<IEdmAction>(model.GetAvailableActions(entityType));
            HashSet<IEdmFunction> allFunctions = new HashSet<IEdmFunction>(model.GetAvailableFunctions(entityType));

            if (selectExpandClause == null)
            {
                SelectedStructuralProperties = allStructuralProperties;
                SelectedNavigationProperties = allNavigationProperties;
                SelectedActions = allActions;
                SelectedFunctions = allFunctions;
                SelectAllDynamicProperties = true;
            }
            else
            {
                if (selectExpandClause.AllSelected)
                {
                    SelectedStructuralProperties = allStructuralProperties;
                    SelectedNavigationProperties = allNavigationProperties;
                    SelectedActions = allActions;
                    SelectedFunctions = allFunctions;
                    SelectAllDynamicProperties = true;
                }
                else
                {
                    BuildSelections(selectExpandClause, allStructuralProperties, allNavigationProperties, allActions, allFunctions);
                    SelectAllDynamicProperties = false;
                }

                BuildExpansions(selectExpandClause, allNavigationProperties);

                // remove expanded navigation properties from the selected navigation properties.
                SelectedNavigationProperties.ExceptWith(ExpandedNavigationProperties.Keys);
            }

            GetExtraQueryParameters(allNavigationProperties, model);
        }
 public ExpandDepthAndCountValidatorTests()
 {
     this.emptyTree = new SelectExpandClause(new SelectItem[0], true);
     var pathToMyDog = new ODataExpandPath(new NavigationPropertySegment(HardCodedTestModel.GetPersonMyDogNavProp(), HardCodedTestModel.GetDogsSet()));
     this.treeWithDepth1 = new SelectExpandClause(new[] { new ExpandedNavigationSelectItem(pathToMyDog, HardCodedTestModel.GetDogsSet(), this.emptyTree) }, true);
     var pathToPerson = new ODataExpandPath(new NavigationPropertySegment(HardCodedTestModel.GetDogMyPeopleNavProp(), HardCodedTestModel.GetPeopleSet()));
     this.treeWithDepth2 = new SelectExpandClause(new[] { new ExpandedNavigationSelectItem(pathToPerson, HardCodedTestModel.GetPeopleSet(), this.treeWithDepth1) }, true);
     var pathToLions = new ODataExpandPath(new NavigationPropertySegment(HardCodedTestModel.GetPersonMyLionsNavProp(), HardCodedTestModel.GetLionSet()));
     this.treeWithWidth2 = new SelectExpandClause(new[] { new ExpandedNavigationSelectItem(pathToMyDog, HardCodedTestModel.GetDogsSet(), this.emptyTree), new ExpandedNavigationSelectItem(pathToLions, HardCodedTestModel.GetLionSet(), this.emptyTree) }, true);
     this.treeWithDepthAndWidth2WithRepeatedParent = new SelectExpandClause(new[] { new ExpandedNavigationSelectItem(pathToPerson, HardCodedTestModel.GetPeopleSet(), this.treeWithWidth2) }, true);
     var pathToPaintings = new ODataExpandPath(new NavigationPropertySegment(HardCodedTestModel.GetPersonMyPaintingsNavProp(), HardCodedTestModel.GetPaintingsSet()));
     this.bigComplexTree = new SelectExpandClause(new[] { 
         new ExpandedNavigationSelectItem(pathToMyDog, HardCodedTestModel.GetDogsSet(), this.treeWithDepthAndWidth2WithRepeatedParent), 
         new ExpandedNavigationSelectItem(pathToLions, HardCodedTestModel.GetLionSet(), this.emptyTree),
         new ExpandedNavigationSelectItem(pathToPaintings, HardCodedTestModel.GetPaintingsSet(), this.emptyTree) }, true);
 }
        public void Ctor_ThatBuildsNestedContext_InitializesRightValues()
        {
            // Arrange
            CustomersModelWithInheritance model = new CustomersModelWithInheritance();
            SelectExpandClause selectExpand = new SelectExpandClause(new SelectItem[0], allSelected: true);
            IEdmNavigationProperty navProp = model.Customer.NavigationProperties().First();
            ODataSerializerContext context = new ODataSerializerContext { EntitySet = model.Customers, Model = model.Model };
            EntityInstanceContext entity = new EntityInstanceContext { SerializerContext = context };

            // Act
            ODataSerializerContext nestedContext = new ODataSerializerContext(entity, selectExpand, navProp);

            // Assert
            Assert.Same(entity, nestedContext.ExpandedEntity);
            Assert.Same(navProp, nestedContext.NavigationProperty);
            Assert.Same(selectExpand, nestedContext.SelectExpandClause);
            Assert.Same(model.Orders, nestedContext.EntitySet);
        }
        private static void ValidateDepth(SelectExpandClause selectExpand, int maxDepth)
        {
            // do a DFS to see if there is any node that is too deep.
            Stack<Tuple<int, SelectExpandClause>> nodesToVisit = new Stack<Tuple<int, SelectExpandClause>>();
            nodesToVisit.Push(Tuple.Create(0, selectExpand));
            while (nodesToVisit.Count > 0)
            {
                Tuple<int, SelectExpandClause> tuple = nodesToVisit.Pop();
                int currentDepth = tuple.Item1;
                SelectExpandClause currentNode = tuple.Item2;

                ExpandedNavigationSelectItem[] expandItems = currentNode.SelectedItems.OfType<ExpandedNavigationSelectItem>().ToArray();

                if (expandItems.Length > 0 &&
                    ((currentDepth == maxDepth &&
                    expandItems.Any(expandItem =>
                        expandItem.LevelsOption == null ||
                        expandItem.LevelsOption.IsMaxLevel ||
                        expandItem.LevelsOption.Level != 0)) ||
                    expandItems.Any(expandItem =>
                        expandItem.LevelsOption != null &&
                        !expandItem.LevelsOption.IsMaxLevel &&
                        (expandItem.LevelsOption.Level > Int32.MaxValue ||
                        expandItem.LevelsOption.Level + currentDepth > maxDepth))))
                {
                    throw new ODataException(
                        Error.Format(SRResources.MaxExpandDepthExceeded, maxDepth, "MaxExpansionDepth"));
                }

                foreach (ExpandedNavigationSelectItem expandItem in expandItems)
                {
                    int depth = currentDepth + 1;

                    if (expandItem.LevelsOption != null && !expandItem.LevelsOption.IsMaxLevel)
                    {
                        // Add the value of $levels for next depth.
                        depth = depth + (int)expandItem.LevelsOption.Level - 1;
                    }

                    nodesToVisit.Push(Tuple.Create(depth, expandItem.SelectAndExpand));
                }
            }
        }
 public void WildcardDoesNotPreemptOtherSelectionItems()
 {
     ODataSelectPath coolPeoplePath = new ODataSelectPath(new OperationSegment(new IEdmOperation[] { HardCodedTestModel.GetChangeStateAction() }, null));
     ODataSelectPath stuffPath = new ODataSelectPath(new OpenPropertySegment("stuff"));
     var expandTree = new SelectExpandClause(new Collection<SelectItem>()
                                 {
                                     new PathSelectItem(coolPeoplePath),
                                     new PathSelectItem(new ODataSelectPath(new NavigationPropertySegment(HardCodedTestModel.GetPaintingOwnerNavProp(), null))),
                                     new PathSelectItem(stuffPath),
                                     new PathSelectItem(new ODataSelectPath(new PropertySegment(HardCodedTestModel.GetPaintingColorsProperty())))
                                 }, false);
     var binder = new SelectBinder(HardCodedTestModel.TestModel, HardCodedTestModel.GetPaintingType(), 800, expandTree);
     var selectToken = new SelectToken(new List<PathSegmentToken>() { new NonSystemToken("*", null, null) });
     var item = binder.Bind(selectToken);
     item.SelectedItems.Should().HaveCount(4)
                .And.Contain(x => x is PathSelectItem && x.As<PathSelectItem>().SelectedPath == coolPeoplePath)
                .And.Contain(x => x is PathSelectItem && x.As<PathSelectItem>().SelectedPath == stuffPath)
                .And.Contain(x => x is PathSelectItem && x.As<PathSelectItem>().SelectedPath.LastSegment is NavigationPropertySegment && x.As<PathSelectItem>().SelectedPath.LastSegment.As<NavigationPropertySegment>().NavigationProperty.Name == HardCodedTestModel.GetPaintingOwnerNavProp().Name)
                .And.Contain(x => x is WildcardSelectItem);
 }
Example #29
0
        public void CreateODataFeed_Ignores_CountValue_ForInnerFeeds()
        {
            // Arrange
            ODataFeedSerializer serializer = new ODataFeedSerializer(new DefaultODataSerializerProvider());
            HttpRequestMessage request = new HttpRequestMessage();
            request.ODataProperties().TotalCount = 42;
            var result = new object[0];
            IEdmNavigationProperty navProp = _customerSet.EntityType().NavigationProperties().First();
            SelectExpandClause selectExpandClause = new SelectExpandClause(new SelectItem[0], allSelected: true);
            EntityInstanceContext entity = new EntityInstanceContext
            {
                SerializerContext =
                    new ODataSerializerContext { Request = request, NavigationSource = _customerSet, Model = _model }
            };
            ODataSerializerContext nestedContext = new ODataSerializerContext(entity, selectExpandClause, navProp);

            // Act
            ODataFeed feed = serializer.CreateODataFeed(result, _customersType, nestedContext);

            // Assert
            Assert.Null(feed.Count);
        }
        private static void ValidateDepth(SelectExpandClause selectExpand, int maxDepth)
        {
            // do a DFS to see if there is any node that is too deep.
            Stack<Tuple<int, SelectExpandClause>> nodesToVisit = new Stack<Tuple<int, SelectExpandClause>>();
            nodesToVisit.Push(Tuple.Create(0, selectExpand));
            while (nodesToVisit.Count > 0)
            {
                Tuple<int, SelectExpandClause> tuple = nodesToVisit.Pop();
                int currentDepth = tuple.Item1;
                SelectExpandClause currentNode = tuple.Item2;

                ExpandedNavigationSelectItem[] expandItems = currentNode.SelectedItems.OfType<ExpandedNavigationSelectItem>().ToArray();
                if (expandItems.Length > 0 && currentDepth == maxDepth)
                {
                    throw new ODataException(
                        Error.Format(SRResources.MaxExpandDepthExceeded, maxDepth, "MaxExpansionDepth"));
                }

                foreach (ExpandedNavigationSelectItem expandItem in expandItems)
                {
                    nodesToVisit.Push(Tuple.Create(currentDepth + 1, expandItem.SelectAndExpand));
                }
            }
        }
 /// <summary>
 /// Create an Expand item using a nav prop, its entity set and a SelectExpandClause
 /// </summary>
 /// <param name="pathToNavigationProperty">the path to the navigation property for this expand item, including any type segments</param>
 /// <param name="navigationSource">the navigation source for this ExpandItem</param>
 /// <param name="selectExpandOption">This level select and any sub expands for this expand item.</param>
 /// <exception cref="System.ArgumentNullException">Throws if input pathToNavigationProperty is null.</exception>
 public ExpandedNavigationSelectItem(ODataExpandPath pathToNavigationProperty, IEdmNavigationSource navigationSource, SelectExpandClause selectExpandOption)
     : this(pathToNavigationProperty, navigationSource, selectExpandOption, null, null, null, null, null, null, null)
 {
 }
Example #32
0
 /// <summary>
 /// Gets a list of strings representing current selected property name in current level.
 /// </summary>
 /// <param name="selectExpandClause">The select expand clause used.</param>
 /// <returns>String list generated from selected items</returns>
 internal static List <string> GetCurrentLevelSelectList(this SelectExpandClause selectExpandClause)
 {
     return(selectExpandClause.SelectedItems.Select(GetSelectString).Where(i => i != null).ToList());
 }
Example #33
0
        /// <summary>
        /// Get sub select and expand clause by property name, if the propertyname is in form of TypeCast/Property, the typeSegment would also be returned.
        /// </summary>
        /// <param name="clause">The root clause.</param>
        /// <param name="propertyName">The property name to navigate to.</param>
        /// <param name="subSelectExpand">The sub select and expand clause under sub property.</param>
        /// <param name="typeSegment">Type cast segment, if exists.</param>
        internal static void GetSubSelectExpandClause(this SelectExpandClause clause, string propertyName, out SelectExpandClause subSelectExpand, out TypeSegment typeSegment)
        {
            subSelectExpand = null;
            typeSegment     = null;

            ExpandedNavigationSelectItem selectedItem = clause
                                                        .SelectedItems
                                                        .OfType <ExpandedNavigationSelectItem>()
                                                        .FirstOrDefault(
                m => m.PathToNavigationProperty.LastSegment != null &&
                m.PathToNavigationProperty.LastSegment.TranslateWith(PathSegmentToStringTranslator.Instance) == propertyName);

            if (selectedItem != null)
            {
                subSelectExpand = selectedItem.SelectAndExpand;
                typeSegment     = selectedItem.PathToNavigationProperty.FirstSegment as TypeSegment;
            }
        }