// Process $levels in SelectedItems. private IEnumerable <SelectItem> ProcessLevels( IEnumerable <SelectItem> selectItems, int levelsMaxLiteralExpansionDepth, ModelBoundQuerySettings querySettings, out bool levelsEncountered, out bool isMaxLevel) { levelsEncountered = false; isMaxLevel = false; IList <SelectItem> items = new List <SelectItem>(); foreach (SelectItem selectItem in selectItems) { ExpandedNavigationSelectItem item = selectItem as ExpandedNavigationSelectItem; if (item == null) { // There is no $levels in non-ExpandedNavigationSelectItem. items.Add(selectItem); } else { bool levelsEncouteredInExpand; bool isMaxLevelInExpand; // Process $levels in ExpandedNavigationSelectItem. ExpandedNavigationSelectItem expandItem = this.ProcessLevels( item, levelsMaxLiteralExpansionDepth, querySettings, out levelsEncouteredInExpand, out isMaxLevelInExpand); if (item.LevelsOption != null && item.LevelsOption.Level > 0 && expandItem == null) { // Abandon this attempt if any of the items failed to expand return(null); } else if (item.LevelsOption != null) { // The expansion would be volatile if any of the expand item is max level isMaxLevel = isMaxLevel || isMaxLevelInExpand; } levelsEncountered = levelsEncountered || levelsEncouteredInExpand; if (expandItem != null) { items.Add(expandItem); } } } return(items); }
internal SelectExpandClause ProcessLevels() { bool levelsEncountered; bool isMaxLevel; ModelBoundQuerySettings querySettings = EdmLibHelpers.GetModelBoundQuerySettings(this.Context.TargetProperty, this.Context.TargetStructuredType, this.Context.Model, this.Context.DefaultQuerySettings); return(this.ProcessLevels(this.SelectExpandClause, this.LevelsMaxLiteralExpansionDepth < 0 ? ODataValidationSettings.DefaultMaxExpansionDepth : this.LevelsMaxLiteralExpansionDepth, querySettings, out levelsEncountered, out isMaxLevel)); }
/// <summary> /// Copy and create new instance of the <see cref="ModelBoundQuerySettings"/> class /// </summary> public ModelBoundQuerySettings(ModelBoundQuerySettings querySettings) { this._maxTop = querySettings.MaxTop; this.PageSize = querySettings.PageSize; this.Countable = querySettings.Countable; this.DefaultEnableFilter = querySettings.DefaultEnableFilter; this.DefaultEnableOrderBy = querySettings.DefaultEnableOrderBy; this.DefaultExpandType = querySettings.DefaultExpandType; this.DefaultMaxDepth = querySettings.DefaultMaxDepth; this.DefaultSelectType = querySettings.DefaultSelectType; this.CopyOrderByConfigurations(querySettings.OrderByConfigurations); this.CopyFilterConfigurations(querySettings.FilterConfigurations); this.CopyExpandConfigurations(querySettings.ExpandConfigurations); this.CopySelectConfigurations(querySettings.SelectConfigurations); }
private static int GetMaxExpandDepth(ModelBoundQuerySettings querySettings, string propertyName) { int result = 0; if (querySettings != null) { ExpandConfiguration expandConfiguration; if (querySettings.ExpandConfigurations.TryGetValue(propertyName, out expandConfiguration)) { result = expandConfiguration.MaxDepth; } else { if (querySettings.DefaultExpandType.HasValue && querySettings.DefaultExpandType != SelectExpandType.Disabled) { result = querySettings.DefaultMaxDepth; } } } return(result); }
// Process $levels in SelectExpandClause. private SelectExpandClause ProcessLevels( SelectExpandClause selectExpandClause, int levelsMaxLiteralExpansionDepth, ModelBoundQuerySettings querySettings, out bool levelsEncountered, out bool isMaxLevel) { levelsEncountered = false; isMaxLevel = false; if (selectExpandClause == null) { return(null); } // Process $levels in SelectItems of SelectExpandClause. IEnumerable <SelectItem> selectItems = this.ProcessLevels( selectExpandClause.SelectedItems, levelsMaxLiteralExpansionDepth, querySettings, out levelsEncountered, out isMaxLevel); if (selectItems == null) { return(null); } else if (levelsEncountered) { return(new SelectExpandClause(selectItems, selectExpandClause.AllSelected)); } else { // Return the original SelectExpandClause if no $levels is found. return(selectExpandClause); } }
// Process $levels in ExpandedNavigationSelectItem. private ExpandedNavigationSelectItem ProcessLevels( ExpandedNavigationSelectItem expandItem, int levelsMaxLiteralExpansionDepth, ModelBoundQuerySettings querySettings, 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; var entityType = expandItem.NavigationSource.EntityType(); IEdmNavigationProperty navigationProperty = (expandItem.PathToNavigationProperty.LastSegment as NavigationPropertySegment).NavigationProperty; ModelBoundQuerySettings nestQuerySettings = EdmLibHelpers.GetModelBoundQuerySettings(navigationProperty, navigationProperty.ToEntityType(), this.Context.Model); // Try different expansion depth until expandItem.SelectAndExpand is successfully expanded while (selectExpandClause == null && level > 0) { selectExpandClause = this.ProcessLevels( expandItem.SelectAndExpand, levelsMaxLiteralExpansionDepth - level, nestQuerySettings, out levelsEncounteredInInnerExpand, out isMaxLevelInInnerExpand); level--; } if (selectExpandClause == null) { return(null); } // Correct level value level++; List <SelectItem> originAutoSelectItems; List <SelectItem> originAutoExpandItems; int maxDepth = GetMaxExpandDepth(querySettings, navigationProperty.Name); if (maxDepth == 0 || levelsMaxLiteralExpansionDepth > maxDepth) { maxDepth = levelsMaxLiteralExpansionDepth; } this.GetAutoSelectExpandItems( entityType, this.Context.Model, expandItem.NavigationSource, selectExpandClause.AllSelected, nestQuerySettings, maxDepth - 1, out originAutoSelectItems, out originAutoExpandItems); if (expandItem.SelectAndExpand.SelectedItems.Any(it => it is PathSelectItem)) { originAutoSelectItems.Clear(); } if (level > 1) { RemoveSameExpandItem(navigationProperty, originAutoExpandItems); } List <SelectItem> autoExpandItems = new List <SelectItem>(originAutoExpandItems); bool hasAutoSelectExpandInExpand = (originAutoSelectItems.Count() + originAutoExpandItems.Count() != 0); bool allSelected = originAutoSelectItems.Count == 0 && selectExpandClause.AllSelected; while (level > 0) { autoExpandItems = RemoveExpandItemExceedMaxDepth(maxDepth - level, originAutoExpandItems); if (item == null) { if (hasAutoSelectExpandInExpand) { currentSelectExpandClause = new SelectExpandClause( new SelectItem[] { }.Concat(selectExpandClause.SelectedItems) .Concat(originAutoSelectItems).Concat(autoExpandItems), allSelected); } else { currentSelectExpandClause = selectExpandClause; } } else if (selectExpandClause.AllSelected) { // Concat the processed items currentSelectExpandClause = new SelectExpandClause( new SelectItem[] { item }.Concat(selectExpandClause.SelectedItems) .Concat(originAutoSelectItems).Concat(autoExpandItems), 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(originAutoSelectItems).Concat(autoExpandItems), 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 = this.ProcessLevels( expandItem.SelectAndExpand, levelsMaxLiteralExpansionDepth - level, nestQuerySettings, out levelsEncounteredInInnerExpand, out isMaxLevelInInnerExpand); } } levelsEncounteredInExpand = levelsEncounteredInExpand || levelsEncounteredInInnerExpand || hasAutoSelectExpandInExpand; isMaxLevelInExpand = isMaxLevelInExpand || isMaxLevelInInnerExpand; return(item); }
private void GetAutoSelectExpandItems( IEdmEntityType baseEntityType, IEdmModel model, IEdmNavigationSource navigationSource, bool isAllSelected, ModelBoundQuerySettings modelBoundQuerySettings, int depth, out List <SelectItem> autoSelectItems, out List <SelectItem> autoExpandItems) { autoSelectItems = new List <SelectItem>(); var autoSelectProperties = EdmLibHelpers.GetAutoSelectProperties(null, baseEntityType, model, modelBoundQuerySettings); foreach (var autoSelectProperty in autoSelectProperties) { List <ODataPathSegment> pathSegments = new List <ODataPathSegment>() { new PropertySegment(autoSelectProperty) }; PathSelectItem pathSelectItem = new PathSelectItem( new ODataSelectPath(pathSegments)); autoSelectItems.Add(pathSelectItem); } autoExpandItems = new List <SelectItem>(); depth--; if (depth < 0) { return; } var autoExpandNavigationProperties = EdmLibHelpers.GetAutoExpandNavigationProperties(null, baseEntityType, model, !isAllSelected, modelBoundQuerySettings); foreach (var navigationProperty in autoExpandNavigationProperties) { 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); modelBoundQuerySettings = EdmLibHelpers.GetModelBoundQuerySettings(navigationProperty, navigationProperty.ToEntityType(), model); List <SelectItem> nestedSelectItems; List <SelectItem> nestedExpandItems; int maxExpandDepth = GetMaxExpandDepth(modelBoundQuerySettings, navigationProperty.Name); if (maxExpandDepth != 0 && maxExpandDepth < depth) { depth = maxExpandDepth; } this.GetAutoSelectExpandItems( currentEdmNavigationSource.EntityType(), model, item.NavigationSource, true, modelBoundQuerySettings, depth, out nestedSelectItems, out nestedExpandItems); selectExpandClause = new SelectExpandClause(nestedSelectItems.Concat(nestedExpandItems), nestedSelectItems.Count == 0); item = new ExpandedNavigationSelectItem(expandPath, currentEdmNavigationSource, selectExpandClause); autoExpandItems.Add(item); if (!isAllSelected || autoSelectProperties.Count() != 0) { PathSelectItem pathSelectItem = new PathSelectItem( new ODataSelectPath(pathSegments)); autoExpandItems.Add(pathSelectItem); } } } }