/// <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; }
/// <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)); } }
/// <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); }
/// <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"); }
/// <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; }
/// <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); }
/// <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); }
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) { }
/// <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()); }
/// <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; } }