// 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 = 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(Context.TargetProperty, Context.TargetStructuredType, Context.Model, Context.DefaultQuerySettings); return(ProcessLevels(SelectExpandClause, LevelsMaxLiteralExpansionDepth < 0 ? ODataValidationSettings.DefaultMaxExpansionDepth : LevelsMaxLiteralExpansionDepth, querySettings, out levelsEncountered, out isMaxLevel)); }
/// <summary> /// Copy and create new instance of the <see cref="ModelBoundQuerySettings"/> class /// </summary> public ModelBoundQuerySettings(ModelBoundQuerySettings querySettings) { _maxTop = querySettings.MaxTop; PageSize = querySettings.PageSize; Countable = querySettings.Countable; DefaultEnableFilter = querySettings.DefaultEnableFilter; DefaultEnableOrderBy = querySettings.DefaultEnableOrderBy; DefaultExpandType = querySettings.DefaultExpandType; DefaultMaxDepth = querySettings.DefaultMaxDepth; DefaultSelectType = querySettings.DefaultSelectType; CopyOrderByConfigurations(querySettings.OrderByConfigurations); CopyFilterConfigurations(querySettings.FilterConfigurations); CopyExpandConfigurations(querySettings.ExpandConfigurations); CopySelectConfigurations(querySettings.SelectConfigurations); }
private static bool CanExpand(this IEdmModel edmModel, IEdmStructuredType structuredType, IEdmProperty property) { // first for back-compability, check the queryable restriction QueryableRestrictionsAnnotation annotation = EdmLibHelpers.GetPropertyRestrictions(property, edmModel); if (annotation != null && annotation.Restrictions.NotExpandable) { return(false); } ModelBoundQuerySettings settings = edmModel.GetModelBoundQuerySettingsOrNull(structuredType, property); if (settings != null && !settings.Expandable(property.Name)) { return(false); } return(true); }
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); }
public static bool IsAutoExpand(IEdmProperty navigationProperty, IEdmProperty pathProperty, IEdmStructuredType pathStructuredType, IEdmModel edmModel, bool isSelectPresent = false, ModelBoundQuerySettings querySettings = null) { QueryableRestrictionsAnnotation annotation = EdmLibHelpers.GetPropertyRestrictions(navigationProperty, edmModel); if (annotation != null && annotation.Restrictions.AutoExpand) { return(!annotation.Restrictions.DisableAutoExpandWhenSelectIsPresent || !isSelectPresent); } if (querySettings == null) { querySettings = EdmLibHelpers.GetModelBoundQuerySettings(pathProperty, pathStructuredType, edmModel); } if (querySettings != null && querySettings.IsAutomaticExpand(navigationProperty.Name)) { return(true); } return(false); }
// 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 = ProcessLevels( selectExpandClause.SelectedItems, levelsMaxLiteralExpansionDepth, querySettings, out levelsEncountered, out isMaxLevel); if (selectItems == null) { return(null); } else if (levelsEncountered) { return(new SelectExpandClause(selectItems, selectExpandClause.AllSelected, selectExpandClause.AllAutoSelected)); } 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(), Context.Model); // Try different expansion depth until expandItem.SelectAndExpand is successfully expanded while (selectExpandClause == null && level > 0) { selectExpandClause = 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; } GetAutoSelectExpandItems( entityType, 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; var typeLevelSettings = EdmLibHelpers.GetModelBoundQuerySettings(entityType, this.Context.Model, this.Context.DefaultQuerySettings); bool allAutoSelected = (typeLevelSettings != null && typeLevelSettings.DefaultSelectType == SelectExpandType.Automatic); 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, allAutoSelected); } 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, allAutoSelected); } 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, allAutoSelected); } // Construct a new ExpandedNavigationSelectItem with current SelectExpandClause. item = new ExpandedNavigationSelectItem( expandItem.PathToNavigationProperty, expandItem.NavigationSource, currentSelectExpandClause, expandItem.FilterOption, expandItem.OrderByOption, expandItem.TopOption, expandItem.SkipOption, expandItem.CountOption, expandItem.SearchOption, null, expandItem.ComputeOption, expandItem.ApplyOption); level--; // Need expand and construct selectExpandClause every time if it is max level in inner expand if (isMaxLevelInInnerExpand) { selectExpandClause = 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; } 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); } } } }
private static void GetAutoExpandPaths(this IEdmModel edmModel, IEdmStructuredType structuredType, IEdmProperty pathProperty, Stack <IEdmElement> nodes, ISet <IEdmStructuredType> visited, IList <ExpandModelPath> results, bool isSelectPresent = false, ModelBoundQuerySettings querySettings = null) { if (visited.Contains(structuredType)) { return; } visited.Add(structuredType); List <IEdmStructuredType> structuredTypes = new List <IEdmStructuredType>(); structuredTypes.Add(structuredType); structuredTypes.AddRange(edmModel.FindAllDerivedTypes(structuredType)); foreach (IEdmStructuredType edmStructuredType in structuredTypes) { IEnumerable <IEdmProperty> properties; if (edmStructuredType == structuredType) { // for base type, let's retrieve its properties and the properties from base type of base type if have. properties = edmStructuredType.Properties(); } else { // for derived type, let's retrieve the declared properties. properties = edmStructuredType.DeclaredProperties; nodes.Push(edmStructuredType); // add a type cast for derived type } foreach (IEdmProperty property in properties) { switch (property.PropertyKind) { case EdmPropertyKind.Structural: IEdmStructuralProperty structuralProperty = (IEdmStructuralProperty)property; IEdmTypeReference typeRef = property.Type.GetElementTypeOrSelf(); if (typeRef.IsComplex() && edmModel.CanExpand(typeRef.AsComplex().ComplexDefinition(), structuralProperty)) { IEdmStructuredType subStructuredType = typeRef.AsStructured().StructuredDefinition(); nodes.Push(structuralProperty); edmModel.GetAutoExpandPaths(subStructuredType, structuralProperty, nodes, visited, results, isSelectPresent, querySettings); nodes.Pop(); } break; case EdmPropertyKind.Navigation: IEdmNavigationProperty navigationProperty = (IEdmNavigationProperty)property; if (IsAutoExpand(navigationProperty, pathProperty, edmStructuredType, edmModel, isSelectPresent, querySettings)) { nodes.Push(navigationProperty); results.Add(new ExpandModelPath(nodes.Reverse())); // found an auto-expand navigation property path nodes.Pop(); } break; } } if (edmStructuredType != structuredType) { nodes.Pop(); // pop the type cast for derived type } } }
public static bool IsAutoSelect(IEdmProperty property, IEdmProperty pathProperty, IEdmStructuredType pathStructuredType, IEdmModel edmModel, ModelBoundQuerySettings querySettings = null) { if (querySettings == null) { querySettings = EdmLibHelpers.GetModelBoundQuerySettings(pathProperty, pathStructuredType, edmModel); } if (querySettings != null && querySettings.IsAutomaticSelect(property.Name)) { return(true); } return(false); }
/// <summary> /// Gets the auto expand paths. /// </summary> /// <param name="edmModel">The Edm model.</param> /// <param name="structuredType">The Edm structured type.</param> /// <param name="property">The property starting from, it can be null.</param> /// <param name="isSelectPresent">Is $select presented.</param> /// <param name="querySettings">The query settings.</param> /// <returns>The auto expand paths.</returns> public static IList <ExpandModelPath> GetAutoExpandPaths(this IEdmModel edmModel, IEdmStructuredType structuredType, IEdmProperty property, bool isSelectPresent = false, ModelBoundQuerySettings querySettings = null) { if (edmModel == null) { throw Error.ArgumentNull(nameof(edmModel)); } if (structuredType == null) { throw Error.ArgumentNull(nameof(structuredType)); } Stack <IEdmElement> nodes = new Stack <IEdmElement>(); ISet <IEdmStructuredType> visited = new HashSet <IEdmStructuredType>(); IList <ExpandModelPath> results = new List <ExpandModelPath>(); // type and property from path is higher priority edmModel.GetAutoExpandPaths(structuredType, property, nodes, visited, results, isSelectPresent, querySettings); Contract.Assert(nodes.Count == 0); return(results); }
/// <summary> /// Gets the auto select paths. /// </summary> /// <param name="edmModel">The Edm model.</param> /// <param name="structuredType">The Edm structured type.</param> /// <param name="pathProperty">The property from path, it can be null.</param> /// <param name="querySettings">The query settings.</param> /// <returns>The auto select paths.</returns> public static IList <SelectModelPath> GetAutoSelectPaths(this IEdmModel edmModel, IEdmStructuredType structuredType, IEdmProperty pathProperty, ModelBoundQuerySettings querySettings = null) { if (edmModel == null) { throw Error.ArgumentNull(nameof(edmModel)); } if (structuredType == null) { throw Error.ArgumentNull(nameof(structuredType)); } List <SelectModelPath> autoSelectProperties = new List <SelectModelPath>(); List <IEdmStructuredType> structuredTypes = new List <IEdmStructuredType>(); structuredTypes.Add(structuredType); structuredTypes.AddRange(edmModel.FindAllDerivedTypes(structuredType)); foreach (IEdmStructuredType edmStructuredType in structuredTypes) { // for top type, let's retrieve its properties and the properties from base type of top type if has. // for derived type, let's retrieve the declared properties. IEnumerable <IEdmStructuralProperty> properties = (edmStructuredType == structuredType) ? edmStructuredType.StructuralProperties() : properties = edmStructuredType.DeclaredStructuralProperties(); foreach (IEdmStructuralProperty property in properties) { if (IsAutoSelect(property, pathProperty, edmStructuredType, edmModel, querySettings)) { if (edmStructuredType == structuredType) { autoSelectProperties.Add(new SelectModelPath(new[] { property })); } else { autoSelectProperties.Add(new SelectModelPath(new IEdmElement[] { edmStructuredType, property })); } } } } return(autoSelectProperties); }
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>(); autoExpandItems = new List <SelectItem>(); if (baseEntityType == null) { return; } IList <SelectModelPath> autoSelectProperties = model.GetAutoSelectPaths(baseEntityType, null, modelBoundQuerySettings); foreach (var autoSelectProperty in autoSelectProperties) { ODataSelectPath odataSelectPath = BuildSelectPath(autoSelectProperty, navigationSource); PathSelectItem pathSelectItem = new PathSelectItem(odataSelectPath); autoSelectItems.Add(pathSelectItem); } depth--; if (depth < 0) { return; } IList <ExpandModelPath> autoExpandNavigationProperties = model.GetAutoExpandPaths(baseEntityType, null, !isAllSelected, modelBoundQuerySettings); foreach (ExpandModelPath itemPath in autoExpandNavigationProperties) { string navigationPath = itemPath.NavigationPropertyPath; IEdmNavigationProperty navigationProperty = itemPath.Navigation; IEdmNavigationSource currentEdmNavigationSource; if (navigationPath != null) { currentEdmNavigationSource = navigationSource.FindNavigationTarget(navigationProperty); } else { currentEdmNavigationSource = navigationSource.FindNavigationTarget(navigationProperty, new EdmPathExpression(navigationPath)); } if (currentEdmNavigationSource != null) { ODataExpandPath expandPath = BuildExpandPath(itemPath, navigationSource, currentEdmNavigationSource); 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; } 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.Any()) { PathSelectItem pathSelectItem = new PathSelectItem(new ODataSelectPath(expandPath)); autoExpandItems.Add(pathSelectItem); } } } }