/// <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="writeContext"/>. /// </summary> /// <param name="entityType">The entity type of the entry that would be written.</param> /// <param name="writeContext">The serializer context to be used while creating the collection.</param> /// <remarks>The default constructor is for unit testing only.</remarks> public SelectExpandNode(IEdmEntityType entityType, ODataSerializerContext writeContext) : this(writeContext.SelectExpandClause, entityType, writeContext.Model) { var queryOptionParser = new ODataQueryOptionParser( writeContext.Model, entityType, writeContext.NavigationSource, _extraQueryParameters); var selectExpandClause = queryOptionParser.ParseSelectAndExpand(); if (selectExpandClause != null) { foreach (SelectItem selectItem in selectExpandClause.SelectedItems) { ExpandedNavigationSelectItem expandItem = selectItem as ExpandedNavigationSelectItem; if (expandItem != null) { ValidatePathIsSupported(expandItem.PathToNavigationProperty); NavigationPropertySegment navigationSegment = (NavigationPropertySegment)expandItem.PathToNavigationProperty.LastSegment; IEdmNavigationProperty navigationProperty = navigationSegment.NavigationProperty; if (!ExpandedNavigationProperties.ContainsKey(navigationProperty)) { ExpandedNavigationProperties.Add(navigationProperty, expandItem.SelectAndExpand); } } } } SelectedNavigationProperties.ExceptWith(ExpandedNavigationProperties.Keys); }
/// <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); }
private void MergeSelectedNavigationProperties(ISet <IEdmNavigationProperty> allNavigationProperties) { if (allNavigationProperties == null) { return; } if (SelectedNavigationProperties == null) { SelectedNavigationProperties = allNavigationProperties; } else { SelectedNavigationProperties.UnionWith(allNavigationProperties); } }
/// <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 <IEdmFunctionImport> allActions = new HashSet <IEdmFunctionImport>(model.GetAvailableProcedures(entityType)); if (selectExpandClause == null) { SelectedStructuralProperties = allStructuralProperties; SelectedNavigationProperties = allNavigationProperties; SelectedActions = allActions; } else { if (selectExpandClause.AllSelected) { SelectedStructuralProperties = allStructuralProperties; SelectedNavigationProperties = allNavigationProperties; SelectedActions = allActions; } else { BuildSelections(selectExpandClause, allStructuralProperties, allNavigationProperties, allActions); } BuildExpansions(selectExpandClause, allNavigationProperties); // remove expanded navigation properties from the selected navigation properties. SelectedNavigationProperties.ExceptWith(ExpandedNavigationProperties.Keys); } }
private void AdjustSelectNavigationProperties() { if (SelectedNavigationProperties != null) { // remove expanded navigation properties from the selected navigation properties. if (ExpandedProperties != null) { SelectedNavigationProperties.ExceptWith(ExpandedProperties.Keys); } // remove referenced navigation properties from the selected navigation properties. if (ReferencedProperties != null) { SelectedNavigationProperties.ExceptWith(ReferencedProperties.Keys); } } if (SelectedNavigationProperties != null && !SelectedNavigationProperties.Any()) { SelectedNavigationProperties = null; } }
/// <summary> /// Creates a new instance of the <see cref="SelectExpandNode"/> class describing the set of structural properties, /// nested 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="structuredType">The structural type of the resource that would be written.</param> /// <param name="model">The <see cref="IEdmModel"/> that contains the given structural type.</param> public SelectExpandNode(SelectExpandClause selectExpandClause, IEdmStructuredType structuredType, IEdmModel model) : this() { if (structuredType == null) { throw Error.ArgumentNull("structuredType"); } if (model == null) { throw Error.ArgumentNull("model"); } // So far, it includes all properties of primitive, enum and collection of them HashSet<IEdmStructuralProperty> allStructuralProperties = new HashSet<IEdmStructuralProperty>(); // So far, it includes all properties of complex and collection of complex HashSet<IEdmStructuralProperty> allComplexStructuralProperties = new HashSet<IEdmStructuralProperty>(); GetStructuralProperties(structuredType, allStructuralProperties, allComplexStructuralProperties); // So far, it includes all navigation properties HashSet<IEdmNavigationProperty> allNavigationProperties; HashSet<IEdmAction> allActions; HashSet<IEdmFunction> allFunctions; IEdmEntityType entityType = structuredType as IEdmEntityType; if (entityType != null) { allNavigationProperties = new HashSet<IEdmNavigationProperty>(entityType.NavigationProperties()); allActions = new HashSet<IEdmAction>(model.GetAvailableActions(entityType)); allFunctions = new HashSet<IEdmFunction>(model.GetAvailableFunctions(entityType)); } else { allNavigationProperties = new HashSet<IEdmNavigationProperty>(); allActions = new HashSet<IEdmAction>(); allFunctions = new HashSet<IEdmFunction>(); } if (selectExpandClause == null) { SelectedStructuralProperties = allStructuralProperties; SelectedComplexProperties = allComplexStructuralProperties; SelectedNavigationProperties = allNavigationProperties; SelectedActions = allActions; SelectedFunctions = allFunctions; SelectAllDynamicProperties = true; } else { if (selectExpandClause.AllSelected) { SelectedStructuralProperties = allStructuralProperties; SelectedComplexProperties = allComplexStructuralProperties; SelectedNavigationProperties = allNavigationProperties; SelectedActions = allActions; SelectedFunctions = allFunctions; SelectAllDynamicProperties = true; } else { // Explicitly set SelectAllDynamicProperties as false, while the BuildSelections method will set it as true // if it meets the select all condition. SelectAllDynamicProperties = false; BuildSelections(selectExpandClause, allStructuralProperties, allComplexStructuralProperties, allNavigationProperties, allActions, allFunctions); } BuildExpansions(selectExpandClause, allNavigationProperties); // remove expanded navigation properties from the selected navigation properties. SelectedNavigationProperties.ExceptWith(ExpandedProperties.Keys); } }
private void BuildSelections( SelectExpandClause selectExpandClause, HashSet<IEdmStructuralProperty> allStructuralProperties, HashSet<IEdmStructuralProperty> allNestedProperties, HashSet<IEdmNavigationProperty> allNavigationProperties, HashSet<IEdmAction> allActions, HashSet<IEdmFunction> allFunctions) { foreach (SelectItem selectItem in selectExpandClause.SelectedItems) { if (selectItem is ExpandedNavigationSelectItem) { continue; } PathSelectItem pathSelectItem = selectItem as PathSelectItem; if (pathSelectItem != null) { ValidatePathIsSupported(pathSelectItem.SelectedPath); ODataPathSegment segment = pathSelectItem.SelectedPath.LastSegment; NavigationPropertySegment navigationPropertySegment = segment as NavigationPropertySegment; if (navigationPropertySegment != null) { IEdmNavigationProperty navigationProperty = navigationPropertySegment.NavigationProperty; if (allNavigationProperties.Contains(navigationProperty)) { SelectedNavigationProperties.Add(navigationProperty); } continue; } PropertySegment structuralPropertySegment = segment as PropertySegment; if (structuralPropertySegment != null) { IEdmStructuralProperty structuralProperty = structuralPropertySegment.Property; if (allStructuralProperties.Contains(structuralProperty)) { SelectedStructuralProperties.Add(structuralProperty); } else if (allNestedProperties.Contains(structuralProperty)) { SelectedComplexProperties.Add(structuralProperty); } continue; } OperationSegment operationSegment = segment as OperationSegment; if (operationSegment != null) { AddOperations(allActions, allFunctions, operationSegment); continue; } DynamicPathSegment dynamicPathSegment = segment as DynamicPathSegment; if (dynamicPathSegment != null) { SelectedDynamicProperties.Add(dynamicPathSegment.Identifier); continue; } throw new ODataException(Error.Format(SRResources.SelectionTypeNotSupported, segment.GetType().Name)); } WildcardSelectItem wildCardSelectItem = selectItem as WildcardSelectItem; if (wildCardSelectItem != null) { SelectedStructuralProperties = allStructuralProperties; SelectedComplexProperties = allNestedProperties; SelectedNavigationProperties = allNavigationProperties; SelectAllDynamicProperties = true; continue; } NamespaceQualifiedWildcardSelectItem wildCardActionSelection = selectItem as NamespaceQualifiedWildcardSelectItem; if (wildCardActionSelection != null) { SelectedActions = allActions; SelectedFunctions = allFunctions; continue; } throw new ODataException(Error.Format(SRResources.SelectionTypeNotSupported, selectItem.GetType().Name)); } }
/// <summary> /// Build the $select item, it maybe $select=complex/abc, $select=abc, $select=nav, etc. /// </summary> /// <param name="pathSelectItem">The expanded reference select item.</param> /// <param name="currentLevelPropertiesInclude">The current properties to include at current level.</param> /// <param name="structuralTypeInfo">The structural type properties.</param> private void BuildSelectItem(PathSelectItem pathSelectItem, IDictionary <IEdmStructuralProperty, SelectExpandIncludedProperty> currentLevelPropertiesInclude, EdmStructuralTypeInfo structuralTypeInfo) { Contract.Assert(pathSelectItem != null && pathSelectItem.SelectedPath != null); Contract.Assert(currentLevelPropertiesInclude != null); Contract.Assert(structuralTypeInfo != null); // Verify and process the $select=abc/xyz/.... ODataSelectPath selectPath = pathSelectItem.SelectedPath; IList <ODataPathSegment> remainingSegments; ODataPathSegment segment = selectPath.GetFirstNonTypeCastSegment(out remainingSegments); PropertySegment firstPropertySegment = segment as PropertySegment; if (firstPropertySegment != null) { if (structuralTypeInfo.IsStructuralPropertyDefined(firstPropertySegment.Property)) { // $select=abc/xyz/... SelectExpandIncludedProperty newPropertySelectItem; if (!currentLevelPropertiesInclude.TryGetValue(firstPropertySegment.Property, out newPropertySelectItem)) { newPropertySelectItem = new SelectExpandIncludedProperty(firstPropertySegment); currentLevelPropertiesInclude[firstPropertySegment.Property] = newPropertySelectItem; } newPropertySelectItem.AddSubSelectItem(remainingSegments, pathSelectItem); } return; } // If the first segment is not a property segment, // that segment must be the last segment, so the remainging segments should be null. Contract.Assert(remainingSegments == null); NavigationPropertySegment navigationSegment = segment as NavigationPropertySegment; if (navigationSegment != null) { // for example: $select=NavigationProperty or $select=NS.VipCustomer/VipNav if (structuralTypeInfo.IsNavigationPropertyDefined(navigationSegment.NavigationProperty)) { if (SelectedNavigationProperties == null) { SelectedNavigationProperties = new HashSet <IEdmNavigationProperty>(); } SelectedNavigationProperties.Add(navigationSegment.NavigationProperty); } return; } OperationSegment operationSegment = segment as OperationSegment; if (operationSegment != null) { // for example: $select=NS.Operation, or, $select=NS.VipCustomer/NS.Operation AddOperations(operationSegment, structuralTypeInfo.AllActions, structuralTypeInfo.AllFunctions); return; } DynamicPathSegment dynamicPathSegment = segment as DynamicPathSegment; if (dynamicPathSegment != null) { if (SelectedDynamicProperties == null) { SelectedDynamicProperties = new HashSet <string>(); } SelectedDynamicProperties.Add(dynamicPathSegment.Identifier); return; } // In fact, we should never be here, because it's verified above throw new ODataException(Error.Format(SRResources.SelectionTypeNotSupported, segment.GetType().Name)); }
private void Initialize(SelectExpandClause selectExpandClause, IEdmStructuredType structuredType, IEdmModel model, bool expandedReference) { if (structuredType == null) { throw Error.ArgumentNull("structuredType"); } if (model == null) { throw Error.ArgumentNull("model"); } // So far, it includes all properties of primitive, enum and collection of them HashSet <IEdmStructuralProperty> allStructuralProperties = new HashSet <IEdmStructuralProperty>(); IEdmEntityType entityType = structuredType as IEdmEntityType; if (expandedReference) { SelectAllDynamicProperties = false; if (entityType != null) { // only need to include the key properties. SelectedStructuralProperties = new HashSet <IEdmStructuralProperty>(entityType.Key()); } } else { // So far, it includes all properties of complex and collection of complex HashSet <IEdmStructuralProperty> allComplexStructuralProperties = new HashSet <IEdmStructuralProperty>(); GetStructuralProperties(structuredType, allStructuralProperties, allComplexStructuralProperties); // So far, it includes all navigation properties HashSet <IEdmNavigationProperty> allNavigationProperties; HashSet <IEdmAction> allActions; HashSet <IEdmFunction> allFunctions; IEnumerable <SelectItem> selectItems = new List <SelectItem>(); if (entityType != null) { allNavigationProperties = new HashSet <IEdmNavigationProperty>(entityType.NavigationProperties()); allActions = new HashSet <IEdmAction>(model.GetAvailableActions(entityType)); allFunctions = new HashSet <IEdmFunction>(model.GetAvailableFunctions(entityType)); } else if (structuredType != null) { allNavigationProperties = new HashSet <IEdmNavigationProperty>(structuredType.NavigationProperties()); // Currently, the library does not support for bounded operations on complex type. allActions = new HashSet <IEdmAction>(); allFunctions = new HashSet <IEdmFunction>(); } else { allNavigationProperties = new HashSet <IEdmNavigationProperty>(); allActions = new HashSet <IEdmAction>(); allFunctions = new HashSet <IEdmFunction>(); } if (selectExpandClause == null) { SelectedStructuralProperties = allStructuralProperties; SelectedComplexProperties = allComplexStructuralProperties; SelectedNavigationProperties = allNavigationProperties; SelectedActions = allActions; SelectedFunctions = allFunctions; SelectAllDynamicProperties = true; } else { if (selectExpandClause.AllSelected) { SelectedStructuralProperties = allStructuralProperties; SelectedComplexProperties = allComplexStructuralProperties; SelectedNavigationProperties = allNavigationProperties; SelectedActions = allActions; SelectedFunctions = allFunctions; SelectAllDynamicProperties = true; } else { // Explicitly set SelectAllDynamicProperties as false, while the BuildSelections method will set it as true // if it meets the select all condition. SelectAllDynamicProperties = false; BuildSelections(selectExpandClause, allStructuralProperties, allComplexStructuralProperties, allNavigationProperties, allActions, allFunctions); } selectItems = selectExpandClause.SelectedItems; } BuildExpansions(selectItems, allNavigationProperties); // remove expanded navigation properties from the selected navigation properties. SelectedNavigationProperties.ExceptWith(ExpandedProperties.Keys); // remove referenced navigation properties from the selected navigation properties. SelectedNavigationProperties.ExceptWith(ReferencedNavigationProperties); } }
private void BuildSelections(SelectExpandClause selectExpandClause, HashSet <IEdmStructuralProperty> allStructuralProperties, HashSet <IEdmNavigationProperty> allNavigationProperties, HashSet <IEdmFunctionImport> allActions) { foreach (SelectItem selectItem in selectExpandClause.SelectedItems) { if (selectItem is ExpandedNavigationSelectItem) { continue; } PathSelectItem pathSelectItem = selectItem as PathSelectItem; if (pathSelectItem != null) { ValidatePathIsSupported(pathSelectItem.SelectedPath); ODataPathSegment segment = pathSelectItem.SelectedPath.LastSegment; NavigationPropertySegment navigationPropertySegment = segment as NavigationPropertySegment; if (navigationPropertySegment != null) { IEdmNavigationProperty navigationProperty = navigationPropertySegment.NavigationProperty; if (allNavigationProperties.Contains(navigationProperty)) { SelectedNavigationProperties.Add(navigationProperty); } continue; } PropertySegment structuralPropertySegment = segment as PropertySegment; if (structuralPropertySegment != null) { IEdmStructuralProperty structuralProperty = structuralPropertySegment.Property; if (allStructuralProperties.Contains(structuralProperty)) { SelectedStructuralProperties.Add(structuralProperty); } continue; } OperationSegment operationSegment = segment as OperationSegment; if (operationSegment != null) { foreach (IEdmFunctionImport action in operationSegment.Operations) { if (allActions.Contains(action)) { SelectedActions.Add(action); } } continue; } throw new ODataException(Error.Format(SRResources.SelectionTypeNotSupported, segment.GetType().Name)); } WildcardSelectItem wildCardSelectItem = selectItem as WildcardSelectItem; if (wildCardSelectItem != null) { SelectedStructuralProperties = allStructuralProperties; SelectedNavigationProperties = allNavigationProperties; continue; } ContainerQualifiedWildcardSelectItem wildCardActionSelection = selectItem as ContainerQualifiedWildcardSelectItem; if (wildCardActionSelection != null) { IEnumerable <IEdmFunctionImport> actionsInThisContainer = allActions.Where(a => a.Container == wildCardActionSelection.Container); foreach (IEdmFunctionImport action in actionsInThisContainer) { SelectedActions.Add(action); } continue; } throw new ODataException(Error.Format(SRResources.SelectionTypeNotSupported, selectItem.GetType().Name)); } }