/// <summary> /// is this selection item a structural or navigation property selection item. /// </summary> /// <param name="selectItem">the selection item to check</param> /// <returns>true if this selection item is a structural property selection item.</returns> internal static bool IsStructuralOrNavigationPropertySelectionItem(SelectItem selectItem) { DebugUtils.CheckNoExternalCallers(); PathSelectItem pathSelectItem = selectItem as PathSelectItem; return(pathSelectItem != null && (pathSelectItem.SelectedPath.LastSegment is NavigationPropertySegment || pathSelectItem.SelectedPath.LastSegment is PropertySegment)); }
private static SelectExpandClause CreateSelectExpandClauseNestedSelectWithComplexType() { ODataSelectPath personNamePath = new ODataSelectPath(new PropertySegment(HardCodedTestModel.GetPersonNameProp())); ODataSelectPath personShoePath = new ODataSelectPath(new PropertySegment(HardCodedTestModel.GetPersonFavoriteDateProp())); ODataSelectPath addrPath = new ODataSelectPath(new PropertySegment(HardCodedTestModel.GetPersonAddressProp())); ODataSelectPath cityPath = new ODataSelectPath(new PropertySegment(HardCodedTestModel.GetAddressCityProperty())); var cityClause = new SelectExpandClause(new List <SelectItem>(), false); cityClause.AddToSelectedItems(new PathSelectItem(cityPath)); var addritem = new PathSelectItem(addrPath); addritem.SelectAndExpand = cityClause; var addritem1 = new PathSelectItem(addrPath); var clause = new SelectExpandClause(new List <SelectItem>(), false); clause.AddToSelectedItems(new PathSelectItem(personShoePath)); clause.AddToSelectedItems(new PathSelectItem(personNamePath)); clause.AddToSelectedItems(addritem); clause.AddToSelectedItems(addritem1); return(clause); }
public void DuplicatedSelectPathInOneDollarSelectWorksAsSingle(string select, string expect) { // Arrange ODataQueryOptionParser parser = new ODataQueryOptionParser(_model.Model, _model.Customer, _model.Customers, new Dictionary <string, string> { { "$select", select } }); // Act SelectExpandClause selectAndExpand = parser.ParseSelectAndExpand(); // Assert Assert.NotNull(selectAndExpand); Assert.False(selectAndExpand.AllSelected); SelectItem selectItem = Assert.Single(selectAndExpand.SelectedItems); PathSelectItem pathSelectItem = Assert.IsType <PathSelectItem>(selectItem); ODataPathSegment pathSegment = Assert.Single(pathSelectItem.SelectedPath); if (expect == "ID") { PropertySegment propertySegment = Assert.IsType <PropertySegment>(pathSegment); Assert.Equal(expect, propertySegment.Identifier); } else { OperationSegment operationSegment = Assert.IsType <OperationSegment>(pathSegment); Assert.Equal(expect, operationSegment.Operations.Single().FullName()); } }
public void NestedTopAndSkipAndCountWithValidExpression() { // Arrange SelectToken select = ParseSelectToken("FavoriteColors($skip=4;$count=false;$top=2)"); // Act SelectExpandClause clause = BinderForPerson.Bind(expandToken: null, selectToken: select); // Assert Assert.NotNull(clause); Assert.NotNull(clause.SelectedItems); // FavoriteColors SelectItem selectItem = Assert.Single(clause.SelectedItems); PathSelectItem subPathSelect = Assert.IsType <PathSelectItem>(selectItem); Assert.NotNull(subPathSelect.SkipOption); Assert.Equal(4, subPathSelect.SkipOption.Value); Assert.NotNull(subPathSelect.CountOption); Assert.False(subPathSelect.CountOption.Value); Assert.NotNull(subPathSelect.TopOption); Assert.Equal(2, subPathSelect.TopOption.Value); }
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)); } } } } }
public override Expression Translate(PathSelectItem item) { _pathSelect = true; Expression expression; if (item.SelectedPath.LastSegment is NavigationPropertySegment) { var segment = (NavigationPropertySegment)item.SelectedPath.LastSegment; expression = Translate(segment, null); } else if (item.SelectedPath.LastSegment is PropertySegment) { var segment = (PropertySegment)item.SelectedPath.LastSegment; _selectItemInfo = new SelectItemInfo(null, segment.Property, null, null); PropertyInfo property = _parameter.Type.GetTypeInfo().GetProperty(segment.Property.Name); expression = Expression.MakeMemberAccess(_parameter, property); } else { throw new InvalidOperationException(item.SelectedPath.LastSegment.GetType().Name + " not supported"); } return(expression); }
private void AddStructuralProperty(IEdmStructuralProperty structuralProperty, PathSelectItem pathSelectItem) { bool isComplexOrCollectComplex = IsComplexOrCollectionComplex(structuralProperty); if (isComplexOrCollectComplex) { if (SelectedComplexProperties == null) { SelectedComplexProperties = new Dictionary <IEdmStructuralProperty, PathSelectItem>(); } SelectedComplexProperties[structuralProperty] = pathSelectItem; } else { if (SelectedStructuralProperties == null) { SelectedStructuralProperties = new HashSet <IEdmStructuralProperty>(); } // for primitive, enum and collection them, needn't care about the nested query options now. // So, skip the path select item. SelectedStructuralProperties.Add(structuralProperty); } }
public void NestedSelectWithValidExpressionOnCollection() { // Arrange SelectToken select = ParseSelectToken("PreviousAddresses($select=Street)"); // Act SelectExpandClause clause = BinderForPerson.Bind(expandToken: null, selectToken: select); // Assert Assert.NotNull(clause); // only one top level $select SelectItem selectItem = Assert.Single(clause.SelectedItems); // it should be "PathSelectItem PathSelectItem pathSelect = Assert.IsType <PathSelectItem>(selectItem); Assert.NotNull(pathSelect.SelectAndExpand); // Street selectItem = Assert.Single(pathSelect.SelectAndExpand.SelectedItems); PathSelectItem subPathSelect = Assert.IsType <PathSelectItem>(selectItem); Assert.Equal("Street", subPathSelect.SelectedPath.ToResourcePathString(ODataUrlKeyDelimiter.Parentheses)); Assert.NotNull(subPathSelect.SelectAndExpand); }
internal static string ParseSelect(this ODataQueryOptions options, DbUtility utility) { if (options.Count != null) { return("count(0)"); } if (options.SelectExpand == null) { return("*"); } if (options.SelectExpand.SelectExpandClause.AllSelected) { return("*"); } List <string> s = new List <string>(); PathSelectItem select = null; foreach (var item in options.SelectExpand.SelectExpandClause.SelectedItems) { select = item as PathSelectItem; if (select != null) { foreach (PropertySegment path in select.SelectedPath) { s.Add(utility.SafeDbObject(path.Property.Name)); } } } return(string.Join(",", s)); }
internal static string ParseSelect(this ExpandedNavigationSelectItem expanded) { if (expanded.CountOption.HasValue) { return("count(*)"); } if (expanded.SelectAndExpand == null) { return("*"); } if (expanded.SelectAndExpand.AllSelected) { return("*"); } List <string> s = new List <string>(); PathSelectItem select = null; foreach (var item in expanded.SelectAndExpand.SelectedItems) { select = item as PathSelectItem; if (select != null) { foreach (PropertySegment path in select.SelectedPath) { s.Add(string.Format("[{0}]", path.Property.Name)); } } } return(string.Join(",", s)); }
public void CreateNamedPropertyExpression_NonDerivedProperty_ReturnsMemberAccessExpression(HandleNullPropagationOption options) { SelectExpandBinder binder = GetBinder <Customer>(_model, options); Expression customer = Expression.Constant(new Customer()); IEdmStructuralProperty homeAddressProperty = _customer.StructuralProperties().Single(c => c.Name == "HomeLocation"); ODataSelectPath selectPath = new ODataSelectPath(new PropertySegment(homeAddressProperty)); PathSelectItem pathSelectItem = new PathSelectItem(selectPath); NamedPropertyExpression namedProperty = binder.CreateNamedPropertyExpression(customer, _customer, pathSelectItem); Assert.NotNull(namedProperty); Assert.Equal("\"HomeLocation\"", namedProperty.Name.ToString()); if (options != HandleNullPropagationOption.True) { Assert.Equal("value(NS.Customer).HomeLocation", namedProperty.Value.ToString()); } else { Assert.Equal("IIF((value(NS.Customer) == null)," + " null," + " value(NS.Customer).HomeLocation)", namedProperty.Value.ToString()); } }
/// <summary> /// Add sub $select item for this include property. /// </summary> /// <param name="remainingSegments">The remaining segments star from this include property.</param> /// <param name="oldSelectItem">The old $select item.</param> public void AddSubSelectItem(IList <ODataPathSegment> remainingSegments, PathSelectItem oldSelectItem) { if (remainingSegments == null) { // Be noted: In ODL v7.6.1, it's not allowed duplicated properties in $select. // for example: "$select=abc($top=2),abc($skip=2)" is not allowed in ODL library. // So, don't worry about the previous setting overrided by other same path. // However, it's possibility in later ODL version (>=7.6.2) to allow duplicated properties in $select. // It that case, please update the codes here otherwise the latter will win. // Besides, $select=abc,abc($top=2) is not allowed in ODL 7.6.1. Contract.Assert(_propertySelectItem == null); _propertySelectItem = oldSelectItem; } else { if (_subSelectItems == null) { _subSelectItems = new List <SelectItem>(); } _subSelectItems.Add(new PathSelectItem(new ODataSelectPath(remainingSegments), oldSelectItem.NavigationSource, oldSelectItem.SelectAndExpand, oldSelectItem.FilterOption, oldSelectItem.OrderByOption, oldSelectItem.TopOption, oldSelectItem.SkipOption, oldSelectItem.CountOption, oldSelectItem.SearchOption, oldSelectItem.ComputeOption)); } }
public void CreateNamedPropertyExpression_WithMultiplePropertyAndType_ReturnsMemberAccessExpression(HandleNullPropagationOption options) { SelectExpandBinder binder = GetBinder <Customer>(_model, options); Expression customer = Expression.Parameter(typeof(Customer)); // output will be different. // Expression customer = Expression.Constant(new Customer()); SelectExpandClause selectExpandClause = ParseSelectExpand("HomeLocation/NS.CnAddress/Street", null); PathSelectItem pathSelectItem = selectExpandClause.SelectedItems.First() as PathSelectItem; NamedPropertyExpression namedProperty = binder.CreateNamedPropertyExpression(customer, _customer, pathSelectItem); Assert.NotNull(namedProperty); /* * Assert.NotNull(namedProperty); * Assert.Equal("\"VipAddress\"", namedProperty.Name.ToString()); * * if (options != HandleNullPropagationOption.True) * { * Assert.Equal("(value(NS.Customer) As VipCustomer).VipAddress", namedProperty.Value.ToString()); * } * else * { * Assert.Equal("IIF(((value(NS.Customer) As VipCustomer) == null)," + * " null," + * " (value(NS.Customer) As VipCustomer).VipAddress)", namedProperty.Value.ToString()); * }*/ }
public void CreateNamedPropertyExpression_WithDerivedProperty_ReturnsMemberAccessExpression(HandleNullPropagationOption options) { SelectExpandBinder binder = GetBinder <Customer>(_model, options); //Expression customer = Expression.Parameter(typeof(Customer)); output will be different. Expression customer = Expression.Constant(new Customer()); IEdmStructuralProperty vipAddressProperty = _vipCustomer.StructuralProperties().Single(c => c.Name == "VipAddress"); ODataSelectPath selectPath = new ODataSelectPath(new TypeSegment(_vipCustomer, _customer, null), new PropertySegment(vipAddressProperty)); PathSelectItem pathSelectItem = new PathSelectItem(selectPath); NamedPropertyExpression namedProperty = binder.CreateNamedPropertyExpression(customer, _customer, pathSelectItem); Assert.NotNull(namedProperty); Assert.Equal("\"VipAddress\"", namedProperty.Name.ToString()); if (options != HandleNullPropagationOption.True) { Assert.Equal("(value(NS.Customer) As VipCustomer).VipAddress", namedProperty.Value.ToString()); } else { Assert.Equal("IIF(((value(NS.Customer) As VipCustomer) == null)," + " null," + " (value(NS.Customer) As VipCustomer).VipAddress)", namedProperty.Value.ToString()); } }
public void CreateNamedPropertyExpression_WithMultipleProperty_ReturnsMemberAccessExpression(HandleNullPropagationOption options) { SelectExpandBinder binder = GetBinder <Customer>(_model, options); //Expression customer = Expression.Parameter(typeof(Customer)); output will be different. Expression customer = Expression.Constant(new Customer()); IEdmStructuralProperty homeLocationProperty = _customer.StructuralProperties().Single(c => c.Name == "HomeLocation"); IEdmStructuralProperty streetProperty = _address.StructuralProperties().Single(c => c.Name == "Street"); ODataSelectPath selectPath = new ODataSelectPath(new PropertySegment(homeLocationProperty), new PropertySegment(streetProperty)); PathSelectItem pathSelectItem = new PathSelectItem(selectPath); NamedPropertyExpression namedProperty = binder.CreateNamedPropertyExpression(customer, _customer, pathSelectItem); Assert.NotNull(namedProperty); /* * Assert.NotNull(namedProperty); * Assert.Equal("\"VipAddress\"", namedProperty.Name.ToString()); * * if (options != HandleNullPropagationOption.True) * { * Assert.Equal("(value(NS.Customer) As VipCustomer).VipAddress", namedProperty.Value.ToString()); * } * else * { * Assert.Equal("IIF(((value(NS.Customer) As VipCustomer) == null)," + * " null," + * " (value(NS.Customer) As VipCustomer).VipAddress)", namedProperty.Value.ToString()); * }*/ }
/// <summary> /// Handle a PathSelectItem /// </summary> /// <param name="item">the item to Handle</param> public override void Handle(PathSelectItem item) { var propertySegment = item.SelectedPath.LastSegment as PropertySegment; var openPropertySegment = item.SelectedPath.LastSegment as DynamicPathSegment; // we ignore the NavigationPropertySegment since we already handle it as ExpandedNavigationSelectItem if (propertySegment != null || openPropertySegment != null) { List <ODataProperty> properties = this.ProjectedEntryWrapper.Resource.Properties == null ? new List <ODataProperty>() : this.ProjectedEntryWrapper.Resource.Properties.ToList(); List <ODataNestedResourceInfoWrapper> nestedResourceInfos = this.ProjectedEntryWrapper.NestedResourceInfoWrappers == null ? new List <ODataNestedResourceInfoWrapper>() : this.ProjectedEntryWrapper.NestedResourceInfoWrappers.ToList(); string propertyName = (propertySegment != null) ? propertySegment.Property.Name : openPropertySegment.Identifier; var property = this.OriginalEntryWrapper.Resource.Properties.SingleOrDefault(p => p.Name == propertyName); if (property != null) { properties.Add(property); } else { var nestedInfo = this.OriginalEntryWrapper.NestedResourceInfoWrappers.SingleOrDefault(n => n.NestedResourceInfo.Name == propertyName); if (nestedInfo != null) { nestedResourceInfos.Add(nestedInfo); } } this.ProjectedEntryWrapper.Resource.Properties = properties.AsEnumerable(); this.ProjectedEntryWrapper.NestedResourceInfoWrappers = nestedResourceInfos.ToList(); } }
public static PathSelectItem ShouldBePathSelectionItem(this SelectItem actual, ODataPath path) { PathSelectItem pathSeleteItem = actual.ShouldBeSelectedItemOfType <PathSelectItem>(); Assert.True(pathSeleteItem.SelectedPath.Equals(path)); return(pathSeleteItem); }
private static IEnumerable <SelectItem> GetAutoExpandedNavigationSelectItems( IEdmEntityType baseEntityType, IEdmModel model, string alreadyExpandedNavigationSourceName, IEdmNavigationSource navigationSource, bool isAllSelected, bool searchDerivedTypeWhenAutoExpand) { var expandItems = new List <SelectItem>(); var autoExpandNavigationProperties = EdmLibHelpers.GetAutoExpandNavigationProperties(baseEntityType, model, searchDerivedTypeWhenAutoExpand); foreach (var navigationProperty in autoExpandNavigationProperties) { if (!alreadyExpandedNavigationSourceName.Equals(navigationProperty.Name)) { IEdmEntityType entityType = navigationProperty.DeclaringEntityType(); IEdmNavigationSource currentEdmNavigationSource = navigationSource.FindNavigationTarget(navigationProperty); if (currentEdmNavigationSource != null) { List <ODataPathSegment> pathSegments = new List <ODataPathSegment>() { new NavigationPropertySegment(navigationProperty, currentEdmNavigationSource) }; ODataExpandPath expandPath = new ODataExpandPath(pathSegments); SelectExpandClause selectExpandClause = new SelectExpandClause(new List <SelectItem>(), true); ExpandedNavigationSelectItem item = new ExpandedNavigationSelectItem(expandPath, currentEdmNavigationSource, selectExpandClause); if (!currentEdmNavigationSource.EntityType().Equals(entityType)) { IEnumerable <SelectItem> nestedSelectItems = GetAutoExpandedNavigationSelectItems( currentEdmNavigationSource.EntityType(), model, alreadyExpandedNavigationSourceName, item.NavigationSource, true, searchDerivedTypeWhenAutoExpand); selectExpandClause = new SelectExpandClause(nestedSelectItems, true); item = new ExpandedNavigationSelectItem(expandPath, currentEdmNavigationSource, selectExpandClause); } expandItems.Add(item); if (!isAllSelected) { PathSelectItem pathSelectItem = new PathSelectItem( new ODataSelectPath(pathSegments)); expandItems.Add(pathSelectItem); } } } } return(expandItems); }
private static Expression BuildOrderBySkipToken(OeSelectItem navigationItem, OrderByClause orderByClause, Expression source, OeJoinBuilder joinBuilder, bool hasSelectItems) { while (orderByClause != null) { var propertyNode = (SingleValuePropertyAccessNode)orderByClause.Expression; if (propertyNode.Source is SingleNavigationNode navigationNode) { OeSelectItem match = null; ExpandedNavigationSelectItem navigationSelectItem = null; do { if ((match = navigationItem.FindHierarchyNavigationItem(navigationNode.NavigationProperty)) != null) { match.AddSelectItem(new OeSelectItem(propertyNode.Property, true)); break; } SelectExpandClause selectExpandClause; if (navigationSelectItem == null) { var pathSelectItem = new PathSelectItem(new ODataSelectPath(new PropertySegment((IEdmStructuralProperty)propertyNode.Property))); selectExpandClause = new SelectExpandClause(new[] { pathSelectItem }, false); } else { selectExpandClause = new SelectExpandClause(new[] { navigationSelectItem }, false); } var segment = new NavigationPropertySegment(navigationNode.NavigationProperty, navigationNode.NavigationSource); navigationSelectItem = new ExpandedNavigationSelectItem(new ODataExpandPath(segment), navigationNode.NavigationSource, selectExpandClause); }while ((navigationNode = navigationNode.Source as SingleNavigationNode) != null); if (navigationSelectItem != null) { if (match == null) { match = navigationItem; } var selectItemTranslator = new OeSelectItemTranslator(match, false, source, joinBuilder, true); navigationSelectItem.TranslateWith(selectItemTranslator); source = selectItemTranslator.Source; } } else { if (hasSelectItems) { navigationItem.AddSelectItem(new OeSelectItem(propertyNode.Property, true)); } } orderByClause = orderByClause.ThenBy; } return(source); }
public void TopOptionSetCorrectly() { // Arrange & Act PathSelectItem select = new PathSelectItem(new ODataSelectPath(), null, null, null, null, 5, null, null, null, null); // Assert Assert.NotNull(select.TopOption); Assert.Equal(5, select.TopOption.Value); }
public void CountQueryOptionSetCorrectly() { // Arrange & Act PathSelectItem select = new PathSelectItem(new ODataSelectPath(), null, null, null, null, null, null, true, null, null); // Assert Assert.NotNull(select.CountOption); Assert.True(select.CountOption.Value); }
public void ComputeOptionSetCorrectly() { // Arrange & Act ComputeClause compute = new ComputeClause(null); PathSelectItem select = new PathSelectItem(new ODataSelectPath(), null, null, null, null, null, null, null, null, compute); // Assert Assert.NotNull(select.ComputeOption); Assert.Same(compute, select.ComputeOption); }
public void SelectExpandOptionSetCorrectly() { // Arrange & Act SelectExpandClause selectAndExpand = new SelectExpandClause(null, true); PathSelectItem select = new PathSelectItem(new ODataSelectPath(), null, selectAndExpand, null, null, null, null, null, null, null); // Assert Assert.NotNull(select.SelectAndExpand); Assert.Same(selectAndExpand, select.SelectAndExpand); }
public void NavigationSourceOptionSetCorrectly() { // Arrange & Act var navigationSource = HardCodedTestModel.GetPeopleSet(); PathSelectItem select = new PathSelectItem(new ODataSelectPath(), navigationSource, null, null, null, null, null, null, null, null); // Assert Assert.NotNull(select.NavigationSource); Assert.Same(navigationSource, select.NavigationSource); }
public void SearchOptionSetCorrectly() { // Arrange & Act SearchClause search = new SearchClause(new SearchTermNode("SearchMe")); PathSelectItem select = new PathSelectItem(new ODataSelectPath(), null, null, null, null, null, null, null, search, null); // Assert Assert.NotNull(select.SearchOption); select.SearchOption.Expression.ShouldBeSearchTermNode("SearchMe"); }
public void PathSelectionItemIsNotImplemented() { FakeHandler handler = new FakeHandler(); PathSelectItem item = new PathSelectItem(new ODataSelectPath() { new PropertySegment(ModelBuildingHelpers.BuildValidPrimitiveProperty()) }); Action visitPath = () => item.HandleWith(handler); visitPath.ShouldThrow <NotImplementedException>(); }
private void ProcessTokenAsPath(NonSystemToken tokenIn) { Debug.Assert(tokenIn != null, "tokenIn != null"); List <ODataPathSegment> pathSoFar = new List <ODataPathSegment>(); IEdmStructuredType currentLevelType = this.edmType; // first, walk through all type segments in a row, converting them from tokens into segments. if (tokenIn.IsNamespaceOrContainerQualified()) { PathSegmentToken firstNonTypeToken; pathSoFar.AddRange(SelectExpandPathBinder.FollowTypeSegments(tokenIn, this.model, this.maxDepth, ref currentLevelType, out firstNonTypeToken)); Debug.Assert(firstNonTypeToken != null, "Did not get last token."); tokenIn = firstNonTypeToken as NonSystemToken; if (tokenIn == null) { throw new ODataException(ODataErrorStrings.SelectPropertyVisitor_SystemTokenInSelect(firstNonTypeToken.Identifier)); } } // next, create a segment for the first non-type segment in the path. ODataPathSegment lastSegment = SelectPathSegmentTokenBinder.ConvertNonTypeTokenToSegment(tokenIn, this.model, currentLevelType); // next, create an ODataPath and add the segments to it. if (lastSegment != null) { pathSoFar.Add(lastSegment); } ODataSelectPath selectedPath = new ODataSelectPath(pathSoFar); var selectionItem = new PathSelectItem(selectedPath); // non-navigation cases do not allow further segments in $select. if (tokenIn.NextToken != null) { throw new ODataException(ODataErrorStrings.SelectBinder_MultiLevelPathInSelect); } // if the selected item is a nav prop, then see if its already there before we add it. NavigationPropertySegment trailingNavPropSegment = selectionItem.SelectedPath.LastSegment as NavigationPropertySegment; if (trailingNavPropSegment != null) { if (this.expandClauseToDecorate.SelectedItems.Any(x => x is PathSelectItem && ((PathSelectItem)x).SelectedPath.Equals(selectedPath))) { return; } } this.expandClauseToDecorate.AddToSelectedItems(selectionItem); }
public void FilterOptionSetCorrectly() { // Arrange & Act BinaryOperatorNode filterExpression = new BinaryOperatorNode(BinaryOperatorKind.Equal, new ConstantNode(1), new ConstantNode(1)); FilterClause filterClause = new FilterClause(filterExpression, new ResourceRangeVariable(ExpressionConstants.It, HardCodedTestModel.GetPersonTypeReference(), HardCodedTestModel.GetPeopleSet())); PathSelectItem select = new PathSelectItem(new ODataSelectPath(), null, null, filterClause, null, null, null, null, null, null); // Assert Assert.NotNull(select.FilterOption); Assert.Same(filterClause, select.FilterOption); }
public void OrderbySetCorrectly() { // Arrange & Act SingleValuePropertyAccessNode propertyAccessNode = new SingleValuePropertyAccessNode(new ConstantNode(1), HardCodedTestModel.GetPersonNameProp()); OrderByClause orderBy = new OrderByClause(null, propertyAccessNode, OrderByDirection.Descending, new ResourceRangeVariable(ExpressionConstants.It, HardCodedTestModel.GetPersonTypeReference(), HardCodedTestModel.GetPeopleSet())); PathSelectItem select = new PathSelectItem(new ODataSelectPath(), null, null, null, orderBy, null, null, null, null, null); // Assert Assert.NotNull(select.OrderByOption); Assert.Same(orderBy, select.OrderByOption); }
private static void HandlePathSelectItem(SelectStatement statement, PathSelectItem item) { var property = item.SelectedPath.FirstSegment as PropertySegment; if (property != null) { statement.Columns(property.Property.Name); } else { throw new NotSupportedException(string.Format("PathSelectItem type '{0}' is not supported.", item.SelectedPath.FirstSegment.GetType().FullName)); } }
/// <summary> /// Handle a PathSelectItem /// </summary> /// <param name="item">the item to Handle</param> public override void Handle(PathSelectItem item) { var propertySegment = item.SelectedPath.LastSegment as PropertySegment; var openPropertySegment = item.SelectedPath.LastSegment as OpenPropertySegment; // we ignore the NavigationPropertySegment since we already handle it as ExpandedNavigationSelectItem if (propertySegment != null || openPropertySegment != null) { List<ODataProperty> properties = this.ProjectedEntry.Properties == null ? new List<ODataProperty>() : this.ProjectedEntry.Properties.ToList(); string propertyName = (propertySegment != null) ? propertySegment.Property.Name : openPropertySegment.PropertyName; properties.Add(this.OriginalEntry.Properties.Single(p => p.Name == propertyName)); this.ProjectedEntry.Properties = properties.AsEnumerable(); } }
private static IEnumerable<SelectItem> GetAutoExpandedNavigationSelectItems( IEdmEntityType baseEntityType, IEdmModel model, string alreadyExpandedNavigationSourceName, IEdmNavigationSource navigationSource, bool isAllSelected, bool searchDerivedTypeWhenAutoExpand) { var expandItems = new List<SelectItem>(); var autoExpandNavigationProperties = EdmLibHelpers.GetAutoExpandNavigationProperties(baseEntityType, model, searchDerivedTypeWhenAutoExpand); foreach (var navigationProperty in autoExpandNavigationProperties) { if (!alreadyExpandedNavigationSourceName.Equals(navigationProperty.Name)) { IEdmEntityType entityType = navigationProperty.DeclaringEntityType(); IEdmNavigationSource currentEdmNavigationSource = navigationSource.FindNavigationTarget(navigationProperty); if (currentEdmNavigationSource != null) { List<ODataPathSegment> pathSegments = new List<ODataPathSegment>() { new NavigationPropertySegment(navigationProperty, currentEdmNavigationSource) }; ODataExpandPath expandPath = new ODataExpandPath(pathSegments); SelectExpandClause selectExpandClause = new SelectExpandClause(new List<SelectItem>(), true); ExpandedNavigationSelectItem item = new ExpandedNavigationSelectItem(expandPath, currentEdmNavigationSource, selectExpandClause); if (!currentEdmNavigationSource.EntityType().Equals(entityType)) { IEnumerable<SelectItem> nestedSelectItems = GetAutoExpandedNavigationSelectItems( currentEdmNavigationSource.EntityType(), model, alreadyExpandedNavigationSourceName, item.NavigationSource, true, searchDerivedTypeWhenAutoExpand); selectExpandClause = new SelectExpandClause(nestedSelectItems, true); item = new ExpandedNavigationSelectItem(expandPath, currentEdmNavigationSource, selectExpandClause); } expandItems.Add(item); if (!isAllSelected) { PathSelectItem pathSelectItem = new PathSelectItem( new ODataSelectPath(pathSegments)); expandItems.Add(pathSelectItem); } } } } return expandItems; }
// Process $levels in ExpandedNavigationSelectItem. private ExpandedNavigationSelectItem ProcessLevels( ExpandedNavigationSelectItem expandItem, int levelsMaxLiteralExpansionDepth, out bool levelsEncounteredInExpand, out bool isMaxLevelInExpand) { int level; isMaxLevelInExpand = false; // $level=x if (expandItem.LevelsOption != null && !expandItem.LevelsOption.IsMaxLevel) { levelsEncounteredInExpand = true; level = (int)expandItem.LevelsOption.Level; if (LevelsMaxLiteralExpansionDepth < 0) { levelsMaxLiteralExpansionDepth = level; } } else { if (levelsMaxLiteralExpansionDepth < 0) { levelsMaxLiteralExpansionDepth = ODataValidationSettings.DefaultMaxExpansionDepth; } if (expandItem.LevelsOption == null) { // no $level levelsEncounteredInExpand = false; level = 1; } else { // $level=max levelsEncounteredInExpand = true; isMaxLevelInExpand = true; level = levelsMaxLiteralExpansionDepth; } } // Do not expand when: // 1. $levels is equal to or less than 0. // 2. $levels value is greater than current MaxExpansionDepth if (level <= 0 || level > levelsMaxLiteralExpansionDepth) { return null; } ExpandedNavigationSelectItem item = null; SelectExpandClause currentSelectExpandClause = null; SelectExpandClause selectExpandClause = null; bool levelsEncounteredInInnerExpand = false; bool isMaxLevelInInnerExpand = false; // Try diffent expansion depth until expandItem.SelectAndExpand is successfully expanded while (selectExpandClause == null && level > 0) { selectExpandClause = ProcessLevels( expandItem.SelectAndExpand, levelsMaxLiteralExpansionDepth - level, out levelsEncounteredInInnerExpand, out isMaxLevelInInnerExpand); level--; } if (selectExpandClause == null) { return null; } // Correct level value level++; var entityType = expandItem.NavigationSource.EntityType(); string alreadyExpandedNavigationSourceName = (expandItem.PathToNavigationProperty.LastSegment as NavigationPropertySegment).NavigationProperty.Name; IEnumerable<SelectItem> autoExpandNavigationSelectItems = GetAutoExpandedNavigationSelectItems( entityType, Context.Model, alreadyExpandedNavigationSourceName, expandItem.NavigationSource, selectExpandClause.AllSelected); bool hasAutoExpandInExpand = (autoExpandNavigationSelectItems.Count() != 0); while (level > 0) { if (item == null) { if (hasAutoExpandInExpand) { currentSelectExpandClause = new SelectExpandClause( new SelectItem[] { }.Concat(selectExpandClause.SelectedItems) .Concat(autoExpandNavigationSelectItems), selectExpandClause.AllSelected); } else { currentSelectExpandClause = selectExpandClause; } } else if (selectExpandClause.AllSelected) { // Concat the processed items currentSelectExpandClause = new SelectExpandClause( new SelectItem[] { item }.Concat(selectExpandClause.SelectedItems) .Concat(autoExpandNavigationSelectItems), selectExpandClause.AllSelected); } else { // PathSelectItem is needed for the expanded item if AllSelected is false. PathSelectItem pathSelectItem = new PathSelectItem( new ODataSelectPath(expandItem.PathToNavigationProperty)); // Keep default SelectItems before expanded item to keep consistent with normal SelectExpandClause SelectItem[] items = new SelectItem[] { item, pathSelectItem }; currentSelectExpandClause = new SelectExpandClause( new SelectItem[] { }.Concat(selectExpandClause.SelectedItems) .Concat(items) .Concat(autoExpandNavigationSelectItems), selectExpandClause.AllSelected); } // Construct a new ExpandedNavigationSelectItem with current SelectExpandClause. item = new ExpandedNavigationSelectItem( expandItem.PathToNavigationProperty, expandItem.NavigationSource, currentSelectExpandClause); level--; // Need expand and construct selectExpandClause every time if it is max level in inner expand if (isMaxLevelInInnerExpand) { selectExpandClause = ProcessLevels( expandItem.SelectAndExpand, levelsMaxLiteralExpansionDepth - level, out levelsEncounteredInInnerExpand, out isMaxLevelInInnerExpand); } } levelsEncounteredInExpand = levelsEncounteredInExpand || levelsEncounteredInInnerExpand || hasAutoExpandInExpand; isMaxLevelInExpand = isMaxLevelInExpand || isMaxLevelInInnerExpand; return item; }
public void ConstructorShouldSetPropertyName() { var item = new PathSelectItem(new ODataSelectPath(new OpenPropertySegment("abc"))); item.SelectedPath.FirstSegment.ShouldBeOpenPropertySegment("abc"); }
/// <summary> /// Handle a PathSelectItem /// </summary> /// <param name="item">the item to Handle</param> public virtual void Handle(PathSelectItem item) { throw new NotImplementedException(); }
private void ProcessTokenAsPath(NonSystemToken tokenIn) { Debug.Assert(tokenIn != null, "tokenIn != null"); List<ODataPathSegment> pathSoFar = new List<ODataPathSegment>(); IEdmStructuredType currentLevelType = this.edmType; // first, walk through all type segments in a row, converting them from tokens into segments. if (tokenIn.IsNamespaceOrContainerQualified()) { PathSegmentToken firstNonTypeToken; pathSoFar.AddRange(SelectExpandPathBinder.FollowTypeSegments(tokenIn, this.model, this.maxDepth, this.resolver, ref currentLevelType, out firstNonTypeToken)); Debug.Assert(firstNonTypeToken != null, "Did not get last token."); tokenIn = firstNonTypeToken as NonSystemToken; if (tokenIn == null) { throw new ODataException(ODataErrorStrings.SelectPropertyVisitor_SystemTokenInSelect(firstNonTypeToken.Identifier)); } } // next, create a segment for the first non-type segment in the path. ODataPathSegment lastSegment = SelectPathSegmentTokenBinder.ConvertNonTypeTokenToSegment(tokenIn, this.model, currentLevelType, resolver); // next, create an ODataPath and add the segments to it. if (lastSegment != null) { pathSoFar.Add(lastSegment); bool hasCollectionInPath = false; // try create a complex type property path. while (true) { // no need to go on if the current property is not of complex type or collection of complex type. currentLevelType = lastSegment.EdmType as IEdmStructuredType; var collectionType = lastSegment.EdmType as IEdmCollectionType; if ((currentLevelType == null || currentLevelType.TypeKind != EdmTypeKind.Complex) && (collectionType == null || collectionType.ElementType.TypeKind() != EdmTypeKind.Complex)) { break; } NonSystemToken nextToken = tokenIn.NextToken as NonSystemToken; if (nextToken == null) { break; } lastSegment = null; // This means last segment a collection of complex type, // current segment can only be type cast and cannot be proprty name. if (currentLevelType == null) { currentLevelType = collectionType.ElementType.Definition as IEdmStructuredType; hasCollectionInPath = true; } else if (!hasCollectionInPath) { // If there is no collection type in the path yet, will try to bind property for the next token // first try bind the segment as property. lastSegment = SelectPathSegmentTokenBinder.ConvertNonTypeTokenToSegment(nextToken, this.model, currentLevelType, resolver); } // then try bind the segment as type cast. if (lastSegment == null) { IEdmStructuredType typeFromNextToken = UriEdmHelpers.FindTypeFromModel(this.model, nextToken.Identifier, this.resolver) as IEdmStructuredType; if (typeFromNextToken.IsOrInheritsFrom(currentLevelType)) { lastSegment = new TypeSegment(typeFromNextToken, /*entitySet*/null); } } // type cast failed too. if (lastSegment == null) { break; } // try move to and add next path segment. tokenIn = nextToken; pathSoFar.Add(lastSegment); } } ODataSelectPath selectedPath = new ODataSelectPath(pathSoFar); var selectionItem = new PathSelectItem(selectedPath); // non-navigation cases do not allow further segments in $select. if (tokenIn.NextToken != null) { throw new ODataException(ODataErrorStrings.SelectBinder_MultiLevelPathInSelect); } // if the selected item is a nav prop, then see if its already there before we add it. NavigationPropertySegment trailingNavPropSegment = selectionItem.SelectedPath.LastSegment as NavigationPropertySegment; if (trailingNavPropSegment != null) { if (this.expandClauseToDecorate.SelectedItems.Any(x => x is PathSelectItem && ((PathSelectItem)x).SelectedPath.Equals(selectedPath))) { return; } } this.expandClauseToDecorate.AddToSelectedItems(selectionItem); }
// Process $levels in ExpandedNavigationSelectItem. private static ExpandedNavigationSelectItem ProcessLevels( ExpandedNavigationSelectItem expandItem, int levelsMaxLiteralExpansionDepth, out bool levelsEncounteredInExpand) { // Call ProcessLevels on SelectExpandClause recursively. SelectExpandClause selectExpandClause = ProcessLevels( expandItem.SelectAndExpand, levelsMaxLiteralExpansionDepth - 1, out levelsEncounteredInExpand); if (expandItem.LevelsOption == null) { if (levelsEncounteredInExpand) { return new ExpandedNavigationSelectItem( expandItem.PathToNavigationProperty, expandItem.NavigationSource, selectExpandClause); } else { // Return the original ExpandedNavigationSelectItem if no $levels is found. return expandItem; } } // There is $levels in current ExpandedNavigationSelectItem. levelsEncounteredInExpand = true; int level = expandItem.LevelsOption.IsMaxLevel ? levelsMaxLiteralExpansionDepth : (int)expandItem.LevelsOption.Level; if (level <= 0) { // Do not expand if $levels is equal to 0. return null; } // Initialize current SelectExpandClause with processed SelectExpandClause. SelectExpandClause currentSelectExpandClause = selectExpandClause; ExpandedNavigationSelectItem item = null; // Construct new ExpandedNavigationSelectItem with recursive expansion. while (level > 0) { // Construct a new ExpandedNavigationSelectItem with current SelectExpandClause. item = new ExpandedNavigationSelectItem( expandItem.PathToNavigationProperty, expandItem.NavigationSource, currentSelectExpandClause); // Update current SelectExpandClause with the new ExpandedNavigationSelectItem. if (selectExpandClause.AllSelected) { currentSelectExpandClause = new SelectExpandClause( new[] { item }.Concat(selectExpandClause.SelectedItems), selectExpandClause.AllSelected); } else { // PathSelectItem is needed for the expanded item if AllSelected is false. PathSelectItem pathSelectItem = new PathSelectItem( new ODataSelectPath(expandItem.PathToNavigationProperty)); currentSelectExpandClause = new SelectExpandClause( new SelectItem[] { item, pathSelectItem }.Concat(selectExpandClause.SelectedItems), selectExpandClause.AllSelected); } level--; } return item; }
/// <summary> /// Writes Selection Item of type PathSelectItem node to string /// </summary> /// <param name="node">Node to write to string</param> /// <returns>String representation of node.</returns> private static string ToString(PathSelectItem node) { return ToSingleLineString(node.SelectedPath); }
// Process $levels in ExpandedNavigationSelectItem. private static ExpandedNavigationSelectItem ProcessLevels( ExpandedNavigationSelectItem expandItem, int levelsMaxLiteralExpansionDepth, out bool levelsEncounteredInExpand, out bool isMaxLevelInExpand) { int level; isMaxLevelInExpand = false; if (expandItem.LevelsOption == null) { levelsEncounteredInExpand = false; level = 1; } else { levelsEncounteredInExpand = true; if (expandItem.LevelsOption.IsMaxLevel) { isMaxLevelInExpand = true; level = levelsMaxLiteralExpansionDepth; } else { level = (int)expandItem.LevelsOption.Level; } } // Do not expand when: // 1. $levels is equal to or less than 0. // 2. $levels value is greater than current MaxExpansionDepth if (level <= 0 || level > levelsMaxLiteralExpansionDepth) { return null; } ExpandedNavigationSelectItem item = null; SelectExpandClause currentSelectExpandClause = null; SelectExpandClause selectExpandClause = null; bool levelsEncounteredInInnerExpand = false; bool isMaxLevelInInnerExpand = false; // Try diffent expansion depth until expandItem.SelectAndExpand is successfully expanded while (selectExpandClause == null && level > 0) { selectExpandClause = ProcessLevels( expandItem.SelectAndExpand, levelsMaxLiteralExpansionDepth - level, out levelsEncounteredInInnerExpand, out isMaxLevelInInnerExpand); level--; } if (selectExpandClause == null) { return null; } // Correct level value level++; while (level > 0) { if (item == null) { currentSelectExpandClause = selectExpandClause; } else if (selectExpandClause.AllSelected) { // Concat the processed items currentSelectExpandClause = new SelectExpandClause( new SelectItem[] { item }.Concat(selectExpandClause.SelectedItems), selectExpandClause.AllSelected); } else { // PathSelectItem is needed for the expanded item if AllSelected is false. PathSelectItem pathSelectItem = new PathSelectItem( new ODataSelectPath(expandItem.PathToNavigationProperty)); // Keep default SelectItems before expanded item to keep consistent with normal SelectExpandClause SelectItem[] items = new SelectItem[] { item, pathSelectItem }; currentSelectExpandClause = new SelectExpandClause( new SelectItem[] { }.Concat(selectExpandClause.SelectedItems).Concat(items), selectExpandClause.AllSelected); } // Construct a new ExpandedNavigationSelectItem with current SelectExpandClause. item = new ExpandedNavigationSelectItem( expandItem.PathToNavigationProperty, expandItem.NavigationSource, currentSelectExpandClause); level--; // Need expand and construct selectExpandClause every time if it is max level in inner expand if (isMaxLevelInInnerExpand) { selectExpandClause = ProcessLevels( expandItem.SelectAndExpand, levelsMaxLiteralExpansionDepth - level, out levelsEncounteredInInnerExpand, out isMaxLevelInInnerExpand); } } levelsEncounteredInExpand = levelsEncounteredInExpand || levelsEncounteredInInnerExpand; isMaxLevelInExpand = isMaxLevelInExpand || isMaxLevelInInnerExpand; return item; }