public void SetIsSetCorrectly() { var set = ModelBuildingHelpers.BuildValidEntitySet(); IEdmType type = set.EntityType(); TypeSegment segment = new TypeSegment(type, set); segment.NavigationSource.Should().BeSameAs(set); }
public void InequalityIsCorrect() { TypeSegment typeSegment1 = new TypeSegment(HardCodedTestModel.GetPersonType(), null); TypeSegment typeSegment2 = new TypeSegment(HardCodedTestModel.GetDogType(), null); BatchSegment batchSegment = BatchSegment.Instance; typeSegment1.Equals(typeSegment2).Should().BeFalse(); typeSegment1.Equals(batchSegment).Should().BeFalse(); }
/// <summary> /// Initializes a new instance of the <see cref="CastSegmentTemplate" /> class. /// </summary> /// <param name="typeSegment">The type segment.</param> public CastSegmentTemplate(TypeSegment typeSegment) { TypeSegment = typeSegment ?? throw Error.ArgumentNull(nameof(typeSegment)); Literal = typeSegment.EdmType.AsElementType().FullTypeName(); IsSingle = typeSegment.EdmType.TypeKind != EdmTypeKind.Collection; }
public static AndConstraint <TypeSegment> ShouldBeTypeSegment(this ODataPathSegment segment, IEdmType type) { segment.Should().BeOfType <TypeSegment>(); TypeSegment typeSegment = segment.As <TypeSegment>(); typeSegment.EdmType.ShouldBeEquivalentTo(type); return(new AndConstraint <TypeSegment>(typeSegment)); }
public static void GetPropertyAndStructuredTypeFromPath(IEnumerable <ODataPathSegment> segments, out IEdmProperty property, out IEdmStructuredType structuredType, out string name) { property = null; structuredType = null; name = String.Empty; string typeCast = String.Empty; if (segments != null) { IEnumerable <ODataPathSegment> reverseSegments = segments.Reverse(); foreach (var segment in reverseSegments) { NavigationPropertySegment navigationPathSegment = segment as NavigationPropertySegment; if (navigationPathSegment != null) { property = navigationPathSegment.NavigationProperty; if (structuredType == null) { structuredType = navigationPathSegment.NavigationProperty.ToEntityType(); } name = navigationPathSegment.NavigationProperty.Name + typeCast; return; } PropertySegment propertyAccessPathSegment = segment as PropertySegment; if (propertyAccessPathSegment != null) { property = propertyAccessPathSegment.Property; if (structuredType == null) { structuredType = GetElementType(property.Type) as IEdmStructuredType; } name = property.Name + typeCast; return; } EntitySetSegment entitySetSegment = segment as EntitySetSegment; if (entitySetSegment != null) { if (structuredType == null) { structuredType = entitySetSegment.EntitySet.EntityType(); } name = entitySetSegment.EntitySet.Name + typeCast; return; } TypeSegment typeSegment = segment as TypeSegment; if (typeSegment != null) { structuredType = GetElementType(typeSegment.EdmType.ToEdmTypeReference(false)) as IEdmStructuredType; typeCast = "/" + structuredType; } } } }
public static TypeSegment ShouldBeTypeSegment(this ODataPathSegment segment, IEdmType actualType, IEdmType expectType) { Assert.NotNull(segment); TypeSegment typeSegment = Assert.IsType <TypeSegment>(segment); Assert.Equal(typeSegment.EdmType.FullTypeName(), actualType.FullTypeName()); Assert.Equal(typeSegment.ExpectedType.FullTypeName(), expectType.FullTypeName()); return(typeSegment); }
/// <summary> /// Initializes a new instance of the <see cref="TypeSegmentTemplate"/> class. /// </summary> /// <param name="segment">The type cast segment.</param> public TypeSegmentTemplate(TypeSegment segment) { if (segment == null) { throw Error.ArgumentNull("segment"); } Segment = segment; }
public void GetNavigationPropertyFromExpandPathWithTypeSegmentThrows() { var segment = new TypeSegment(HardCodedTestModel.GetHomeAddressType(), null); ODataPath odataPath = new ODataPath(segment); Action uriParserHelpersAction = () => UriEdmHelpers.GetNavigationPropertyFromExpandPath(odataPath); uriParserHelpersAction.Throws <ODataException>( Strings.ExpandItemBinder_TypeSegmentNotFollowedByPath); }
public void GetMostDerivedTypeFromPathWithTypeSegmentAndInheritedTypeReturnsInheritedType() { var segment = new TypeSegment(HardCodedTestModel.GetHomeAddressType(), null); ODataPath odataPath = new ODataPath(segment); TypeSegment typeSegment = odataPath.FirstSegment as TypeSegment; IEdmType type = typeSegment.EdmType; var result = UriEdmHelpers.GetMostDerivedTypeFromPath(odataPath, type); Assert.Equal(type, result); }
public override void Handle(TypeSegment segment) { this.ThrowIfResolved(); this.Type = segment.EdmType; this.ElementType = this.GetElementType(this.Type); this.childSegments.Add(segment); this.canonicalSegments.Add(segment); }
public void GetMostDerivedTypeFromPathWithTypeSegmentAndNotInheritedTypeReturnsNotInheritedType() { var segment = new TypeSegment(HardCodedTestModel.GetHomeAddressType(), null); ODataPath odataPath = new ODataPath(segment); IEdmEntityType astonishing = new EdmEntityType("AwesomeNamespace", "AstonishingEntity", null, false, false); IEdmEntityReferenceType entityRef = new EdmEntityReferenceType(astonishing); var result = UriEdmHelpers.GetMostDerivedTypeFromPath(odataPath, entityRef); Assert.Equal(entityRef, result); }
/// <summary> /// Translate a TypeSegment /// </summary> /// <param name="segment">the segment to Translate</param> /// <returns>Defined by the implementer</returns> public override string Translate(TypeSegment segment) { IEdmType type = segment.EdmType; IEdmCollectionType collectionType = type as IEdmCollectionType; if (collectionType != null) { type = collectionType.ElementType.Definition; } return("/" + type.FullTypeName()); }
/// <summary> /// Translate a TypeSegment /// </summary> /// <param name="segment">the segment to Translate</param> /// <returns>Translated WebApi path segment</returns> public override IEnumerable <ODataPathSegment> Translate(TypeSegment segment) { if (segment.EdmType.TypeKind == EdmTypeKind.Entity) { yield return(new CastPathSegment((IEdmEntityType)segment.EdmType)); } else { yield return(new CastPathSegment( (IEdmEntityType)((IEdmCollectionType)segment.EdmType).ElementType.Definition)); } }
/// <summary> /// Translate a TypeSegment /// </summary> /// <param name="segment">the segment to Translate</param> /// <returns>Defined by the implementer</returns> public override string Translate(TypeSegment segment) { Debug.Assert(segment != null, "segment != null"); IEdmType type = segment.EdmType; IEdmCollectionType collectionType = type as IEdmCollectionType; if (collectionType != null) { type = collectionType.ElementType.Definition; } return("/" + type.ODataFullName()); }
/// <summary> /// Initializes a new instance of the <see cref="CastSegmentTemplate" /> class. /// </summary> /// <param name="castType">The cast Edm type.</param> /// <param name="expectedType">The expected Edm type.</param> /// <param name="navigationSource">The target navigation source. it could be null.</param> public CastSegmentTemplate(IEdmType castType, IEdmType expectedType, IEdmNavigationSource navigationSource) { if (castType == null) { throw Error.ArgumentNull(nameof(castType)); } if (expectedType == null) { throw Error.ArgumentNull(nameof(expectedType)); } TypeSegment = new TypeSegment(castType, expectedType, navigationSource); }
/// <summary> /// Follow an ODataPath from to get the most derived type /// </summary> /// <param name="path">the path to follow</param> /// <param name="startingType">the starting type before beginning to walk the path.</param> /// <returns>the most derived type in the path.</returns> public static IEdmType GetMostDerivedTypeFromPath(ODataPath path, IEdmType startingType) { IEdmType currentType = startingType; foreach (ODataPathSegment currentSegment in path) { TypeSegment typeSegment = currentSegment as TypeSegment; if (typeSegment != null && typeSegment.EdmType.IsOrInheritsFrom(currentType)) { currentType = typeSegment.EdmType; } } return(currentType); }
private static void Test(IEdmModel model) { IEdmEntityType order = model.SchemaElements.OfType <IEdmEntityType>().First(c => c.Name == "Order"); IEdmEntityType customer = model.SchemaElements.OfType <IEdmEntityType>().First(c => c.Name == "Customer"); IEdmEntityType vipCustomer = model.SchemaElements.OfType <IEdmEntityType>().First(c => c.Name == "VipCustomer"); IEdmNavigationProperty navProp = order.FindProperty("Customer") as IEdmNavigationProperty; IEdmEntitySet customers = model.EntityContainer.FindEntitySet("Customers"); IEdmEntitySet orders = model.EntityContainer.FindEntitySet("Orders"); ODataPathSegment navSegment = new NavigationPropertySegment(navProp, orders); ODataPathSegment typeSegment = new TypeSegment(vipCustomer, customer, customers); // this throw: The last segment, and only the last segment, must be a navigation property in $expand. // ODataExpandPath path = new ODataExpandPath(navSegment, typeSegment); }
public void TryMatch_ReturnsTrue() { // Arrange EdmEntityType entityType = new EdmEntityType("NS", "entity"); TypeSegmentTemplate template = new TypeSegmentTemplate(new TypeSegment(entityType, null)); TypeSegment segment = new TypeSegment(entityType, null); // Act Dictionary <string, object> values = new Dictionary <string, object>(); bool result = template.TryMatch(segment, values); // Assert Assert.True(result); Assert.Empty(values); }
public void Translate_TypeSegment_To_CastPathSegment_Works() { // Arrange IEdmEntitySet entityset = _model.FindDeclaredEntitySet("RoutingCustomers"); IEdmEntityType entityType = _model.FindDeclaredType("System.Web.OData.Routing.RoutingCustomer") as IEdmEntityType; TypeSegment segment = new TypeSegment(entityType, entityset); // Act IEnumerable<ODataPathSegment> segments = _translator.Translate(segment); // Assert ODataPathSegment pathSegment = Assert.Single(segments); CastPathSegment castPathSegment = Assert.IsType<CastPathSegment>(pathSegment); Assert.Same(entityType, castPathSegment.CastType); }
/// <summary> /// Handle a TypeSegment, we use "cast" for type segment. /// </summary> /// <param name="segment">the segment to handle</param> public override void Handle(TypeSegment segment) { Contract.Assert(segment != null); _navigationSource = segment.NavigationSource; // Uri literal does not use the collection type. IEdmType elementType = segment.EdmType; if (segment.EdmType.TypeKind == EdmTypeKind.Collection) { elementType = ((IEdmCollectionType)segment.EdmType).ElementType.Definition; } _pathUriLiteral.Add(elementType.FullTypeName()); }
public void TryMatch_ReturnsFalse() { // Arrange EdmEntityType entityType1 = new EdmEntityType("NS", "entity1"); EdmEntityType entityType2 = new EdmEntityType("NS", "entity2"); TypeSegmentTemplate template = new TypeSegmentTemplate(new TypeSegment(entityType1, null)); TypeSegment segment = new TypeSegment(entityType2, null); // Act Dictionary <string, object> values = new Dictionary <string, object>(); bool result = template.TryMatch(segment, values); // Assert Assert.False(result); }
public void Translate_TypeSegment_To_CastPathSegment_Works() { // Arrange IEdmEntitySet entityset = _model.FindDeclaredEntitySet("RoutingCustomers"); IEdmEntityType entityType = _model.FindDeclaredType("System.Web.OData.Routing.RoutingCustomer") as IEdmEntityType; TypeSegment segment = new TypeSegment(entityType, entityset); // Act IEnumerable <ODataPathSegment> segments = _translator.Translate(segment); // Assert ODataPathSegment pathSegment = Assert.Single(segments); CastPathSegment castPathSegment = Assert.IsType <CastPathSegment>(pathSegment); Assert.Same(entityType, castPathSegment.CastType); }
public static string ToUriLiteral(this TypeSegment segment) { if (segment == null) { throw Error.ArgumentNull("segment"); } IEdmType elementType = segment.EdmType; if (segment.EdmType.TypeKind == EdmTypeKind.Collection) { elementType = ((IEdmCollectionType)segment.EdmType).ElementType.Definition; } return(elementType.FullTypeName()); }
/// <summary> /// Handle a TypeSegment, we use "cast" for type segment. /// </summary> /// <param name="segment">the segment to handle</param> public override void Handle(TypeSegment segment) { _navigationSource = segment.NavigationSource; _pathTemplate.Add(ODataSegmentKinds.Cast); // cast // Uri literal does not use the collection type. IEdmType elementType = segment.EdmType; if (segment.EdmType.TypeKind == EdmTypeKind.Collection) { elementType = ((IEdmCollectionType)segment.EdmType).ElementType.Definition; } _pathUriLiteral.Add(elementType.FullTypeName()); }
public void TranslateCastSegmentTemplate_ReturnsODataTypeSegment() { // Arrange EdmEntityType baseType = new EdmEntityType("NS", "base"); EdmEntityType subType = new EdmEntityType("NS", "sub", baseType); CastSegmentTemplate template = new CastSegmentTemplate(subType, baseType, null); ODataTemplateTranslateContext context = new ODataTemplateTranslateContext(); // Act ODataPathSegment actual = template.Translate(context); // Assert Assert.NotNull(actual); TypeSegment typeSegment = Assert.IsType <TypeSegment>(actual); Assert.Same(subType, typeSegment.EdmType); }
public void ODataPathSegmentHandler_Handles_TypeCastSegment() { // Arrange ODataPathSegmentHandler handler = new ODataPathSegmentHandler(); EdmEntityType customer = new EdmEntityType("NS", "Customer"); EdmEntityType vipCustomer = new EdmEntityType("NS", "VipCustomer", customer); EdmEntityContainer entityContainer = new EdmEntityContainer("NS", "Default"); EdmEntitySet customers = entityContainer.AddEntitySet("Customers", customer); TypeSegment segment = new TypeSegment(vipCustomer, customer, customers); // Act handler.Handle(segment); // Assert Assert.Equal("NS.VipCustomer", handler.PathLiteral); Assert.Same(customers, handler.NavigationSource); }
/// <summary> /// Translate a TypeSegment /// </summary> /// <param name="segment">the segment to Translate</param> /// <returns>Translated WebApi path segment</returns> public override IEnumerable <ODataPathSegment> Translate(TypeSegment segment) { IEdmType elementType = segment.EdmType; if (segment.EdmType.TypeKind == EdmTypeKind.Collection) { elementType = ((IEdmCollectionType)segment.EdmType).ElementType.Definition; } if (elementType.TypeKind == EdmTypeKind.Entity) { yield return(new CastPathSegment((IEdmEntityType)elementType)); } else if (elementType.TypeKind == EdmTypeKind.Complex) { yield return(new ComplexCastPathSegment((IEdmComplexType)elementType)); } }
/// <summary> /// Translate TypeSegment to linq expression. /// </summary> /// <param name="segment">The TypeSegment</param> /// <returns>The linq expression</returns> public override Expression Translate(TypeSegment segment) { if (this.LastQueryTarget.IsEntitySet) { Type baseType = EdmClrTypeUtils.GetInstanceType(this.LastQueryTarget.ElementType.FullTypeName()); Type instanceType = EdmClrTypeUtils.GetInstanceType(((IEdmCollectionType)segment.EdmType).ElementType); // A set return now is a IEnumable, try to convert to IQueryable. this.ResultExpression = Expression.Call(typeof(Queryable), AsQueryableMethod, new Type[] { baseType }, this.ResultExpression); // Convert to .Where(it=> it is Type) ParameterExpression parameter = Expression.Parameter(baseType, "it"); Expression body = Expression.TypeIs(parameter, instanceType); this.ResultExpression = Expression.Call(typeof(Queryable), WhereMethodName, new Type[] { baseType }, this.ResultExpression, Expression.Quote(Expression.Lambda(body, parameter))); this.ResultExpression = Expression.Call(typeof(Queryable), CastMethodName, new[] { instanceType }, this.ResultExpression); } else if (this.LastQueryTarget.TypeKind == EdmTypeKind.Entity) { Type instanceType = EdmClrTypeUtils.GetInstanceType(segment.EdmType.FullTypeName()); this.ResultExpression = Expression.Convert(this.ResultExpression, instanceType); } else if (this.LastQueryTarget.Property != null) { if (this.LastQueryTarget.TypeKind == EdmTypeKind.Complex) { Type instanceType = EdmClrTypeUtils.GetInstanceType(segment.EdmType.FullTypeName()); this.ResultExpression = Expression.Convert(this.ResultExpression, instanceType); } else { // This code should not be hit. It should be prevented by UriParser. throw new ApplicationException( string.Format("PropertySegment with TypeKind '{0}' following by TypeSegment is invalid", this.LastQueryTarget.TypeKind)); } } else { throw Utility.BuildException(HttpStatusCode.NotImplemented, "Unsupported URI segment before TypeSegment", null); } this.LastProcessedSegment = segment; return(this.ResultExpression); }
public void ODataPathSegmentToTemplateHandler_Handles_TypeCast() { // Arrange ODataPathSegmentToTemplateHandler handler = new ODataPathSegmentToTemplateHandler(null); EdmEntityType customer = new EdmEntityType("NS", "Customer"); EdmEntityType vipCustomer = new EdmEntityType("NS", "VipCustomer", customer); EdmEntityContainer entityContainer = new EdmEntityContainer("NS", "Default"); EdmEntitySet customers = entityContainer.AddEntitySet("Customers", customer); TypeSegment segment = new TypeSegment(vipCustomer, customer, customers); // Act handler.Handle(segment); // Assert ODataSegmentTemplate segmentTemplate = Assert.Single(handler.Templates); Assert.IsType <CastSegmentTemplate>(segmentTemplate); }
/// <summary> /// Follow an ODataPath from an Expand to get the Final Nav Prop /// </summary> /// <param name="path">the path to follow</param> /// <returns>the navigation property at the end of that path.</returns> /// <exception cref="ODataException">Throws if the last segment in the path is not a nav prop.</exception> public static IEdmNavigationProperty GetNavigationPropertyFromExpandPath(ODataPath path) { NavigationPropertySegment navPropSegment = null; foreach (ODataPathSegment currentSegment in path) { TypeSegment typeSegment = currentSegment as TypeSegment; navPropSegment = currentSegment as NavigationPropertySegment; if (typeSegment == null && navPropSegment == null) { throw new ODataException(OData.Core.Strings.ExpandItemBinder_TypeSegmentNotFollowedByPath); } } if (navPropSegment == null) { throw new ODataException(OData.Core.Strings.ExpandItemBinder_TypeSegmentNotFollowedByPath); } else { return(navPropSegment.NavigationProperty); } }
public void GetFirstNonTypeCastSegment_WorksForSelectPathWithFirstNonTypeSegmentAtLast() { // Arrange EdmEntityType entityType = new EdmEntityType("NS", "Customer"); IEdmStructuralProperty property = entityType.AddStructuralProperty("Id", EdmPrimitiveTypeKind.String); ODataPathSegment firstTypeSegment = new TypeSegment(entityType, null); ODataPathSegment secondTypeSegment = new TypeSegment(entityType, null); ODataPathSegment firstPropertySegment = new PropertySegment(property); ODataSelectPath selectPath = new ODataSelectPath( firstTypeSegment, secondTypeSegment, firstPropertySegment); // Act IList <ODataPathSegment> remainingSegments; ODataPathSegment firstNonTypeSegment = selectPath.GetFirstNonTypeCastSegment(out remainingSegments); // Assert Assert.NotNull(firstNonTypeSegment); Assert.Same(firstPropertySegment, firstNonTypeSegment); Assert.Null(remainingSegments); }
public void TypeSetCorrectly() { IEdmType type = ModelBuildingHelpers.BuildValidEntityType(); TypeSegment segment = new TypeSegment(type, null); segment.EdmType.Should().BeSameAs(type); }
/// <summary> /// Handle a TypeSegment /// </summary> /// <param name="segment">the segment to Handle</param> public virtual void Handle(TypeSegment segment) { throw new NotImplementedException(); }
public void EqualityIsCorrect() { TypeSegment typeSegment1 = new TypeSegment(HardCodedTestModel.GetPersonType(), null); TypeSegment typeSegment2 = new TypeSegment(HardCodedTestModel.GetPersonType(), null); typeSegment1.Equals(typeSegment2).Should().BeTrue(); }
public void SelectComplexCollectionPropertyWithCast() { var selectItem = ParseSingleSelectForPerson("PreviousAddresses/Fully.Qualified.Namespace.HomeAddress"); ODataPathSegment[] segments = new ODataPathSegment[2]; segments[0] = new PropertySegment(HardCodedTestModel.GetPersonPreviousAddressesProp()); segments[1] = new TypeSegment(HardCodedTestModel.GetHomeAddressType(), null); selectItem.ShouldBePathSelectionItem(new ODataPath(segments)); }
/// <summary> /// Binds the paths from the request's $select query option to the sets/types/properties from the metadata provider of the service. /// </summary> /// <param name="requestDescription">The request description.</param> /// <param name="dataService">The data service.</param> /// <param name="selectQueryOption">The raw value of the $select query option.</param> /// <returns>The bound select segments.</returns> internal static IList<IList<SelectItem>> BindSelectSegments(RequestDescription requestDescription, IDataService dataService, string selectQueryOption) { Debug.Assert(requestDescription != null, "requestDescription != null"); Debug.Assert(dataService != null, "dataService != null"); if (string.IsNullOrEmpty(selectQueryOption)) { return new List<IList<SelectItem>>(); } // Throw if $select requests have been disabled by the user Debug.Assert(dataService.Configuration != null, "dataService.Configuration != null"); if (!dataService.Configuration.DataServiceBehavior.AcceptProjectionRequests) { throw DataServiceException.CreateBadRequestError(Strings.DataServiceConfiguration_ProjectionsNotAccepted); } IList<IList<string>> selectPathsAsText = SplitSelect(selectQueryOption, dataService.Provider); Debug.Assert(selectPathsAsText != null, "selectPathsAsText != null"); List<IList<SelectItem>> boundSegments = new List<IList<SelectItem>>(selectPathsAsText.Count); if (selectPathsAsText.Count == 0) { return boundSegments; } ValidateSelectIsAllowedForRequest(requestDescription); MetadataProviderEdmModel metadataProviderEdmModel = dataService.Provider.GetMetadataProviderEdmModel(); for (int i = selectPathsAsText.Count - 1; i >= 0; i--) { IList<string> path = selectPathsAsText[i]; List<SelectItem> boundSegmentPath = new List<SelectItem>(path.Count); boundSegments.Add(boundSegmentPath); ResourceType targetResourceType = requestDescription.TargetResourceType; ResourceSetWrapper targetResourceSet = requestDescription.TargetResourceSet; // if we get to here, we're building a partial selection List<TypeSegment> typeSegments = new List<TypeSegment>(); bool previousSegmentIsTypeSegment = false; for (int j = 0; j < path.Count; j++) { string pathSegment = path[j]; bool lastPathSegment = (j == path.Count - 1); // '*' is special, it means "Project all immediate properties on this level." if (pathSegment == "*") { Debug.Assert(lastPathSegment, "A wildcard select segment must be the last one. This should have been checked already when splitting appart the paths."); boundSegmentPath.Add(CreateWildcardSelection()); continue; } bool nameIsContainerQualified; string nameFromContainerQualifiedName = dataService.Provider.GetNameFromContainerQualifiedName(pathSegment, out nameIsContainerQualified); if (nameFromContainerQualifiedName == "*") { Debug.Assert(lastPathSegment, "A wildcard select segment must be the last one. This should have been checked already when splitting appart the paths."); Debug.Assert(nameIsContainerQualified, "nameIsContainerQualified == true"); boundSegmentPath.Add(CreateContainerQualifiedWildcardSelection(metadataProviderEdmModel)); continue; } ResourceProperty property = targetResourceType.TryResolvePropertyName(pathSegment); if (property == null) { ResourceType resolvedResourceType = WebUtil.ResolveTypeIdentifier(dataService.Provider, pathSegment, targetResourceType, previousSegmentIsTypeSegment); if (resolvedResourceType != null) { previousSegmentIsTypeSegment = true; if (lastPathSegment) { throw DataServiceException.CreateBadRequestError(Strings.RequestQueryProcessor_QueryParametersPathCannotEndInTypeIdentifier(XmlConstants.HttpQueryStringSelect, resolvedResourceType.FullName)); } targetResourceType = resolvedResourceType; // Whenever we encounter the type segment, we need to only verify that the MPV is set to 3.0 or higher. // There is no need to check for request DSV, request MinDSV or request MaxDSV since there are no protocol changes in // the payload for uri's with type identifier. requestDescription.VerifyProtocolVersion(VersionUtil.Version3Dot0, dataService); IEdmSchemaType edmType = metadataProviderEdmModel.EnsureSchemaType(targetResourceType); TypeSegment typeSegment = new TypeSegment(edmType); typeSegments.Add(typeSegment); continue; } previousSegmentIsTypeSegment = false; // If the currentResourceType is an open type, we require the service action name to be fully qualified or else we treat it as an open property name. if (!targetResourceType.IsOpenType || nameIsContainerQualified) { // Note that if the service does not implement IDataServiceActionProvider and the MaxProtocolVersion < V3, // GetActionsBoundToAnyTypeInResourceSet() would simply return an empty ServiceOperationWrapper collection. Debug.Assert(dataService.ActionProvider != null, "dataService.ActionProvider != null"); IEnumerable<OperationWrapper> allOperationsInSet = dataService.ActionProvider.GetActionsBoundToAnyTypeInResourceSet(targetResourceSet); List<OperationWrapper> selectedServiceActions = allOperationsInSet.Where(o => o.Name == nameFromContainerQualifiedName).ToList(); if (selectedServiceActions.Count > 0) { if (!lastPathSegment) { throw DataServiceException.CreateBadRequestError(Strings.RequestQueryProcessor_ServiceActionMustBeLastSegmentInSelect(pathSegment)); } boundSegmentPath.Add(CreateOperationSelection(metadataProviderEdmModel, selectedServiceActions, typeSegments)); continue; } } if (!targetResourceType.IsOpenType) { throw DataServiceException.CreateSyntaxError(Strings.RequestUriProcessor_PropertyNotFound(targetResourceType.FullName, pathSegment)); } if (!lastPathSegment) { // Open navigation properties are not supported on OpenTypes. throw DataServiceException.CreateBadRequestError(Strings.OpenNavigationPropertiesNotSupportedOnOpenTypes(pathSegment)); } boundSegmentPath.Add(CreateOpenPropertySelection(pathSegment, typeSegments)); } else { previousSegmentIsTypeSegment = false; ValidateSelectedProperty(targetResourceType, property, lastPathSegment); boundSegmentPath.Add(CreatePropertySelection(metadataProviderEdmModel, targetResourceType, property, typeSegments)); if (property.TypeKind == ResourceTypeKind.EntityType) { targetResourceSet = dataService.Provider.GetResourceSet(targetResourceSet, targetResourceType, property); targetResourceType = property.ResourceType; } } } // Note that this check is also covering cases where a type segment is followed by a wildcard. if (previousSegmentIsTypeSegment) { throw DataServiceException.CreateBadRequestError(Strings.RequestQueryProcessor_QueryParametersPathCannotEndInTypeIdentifier(XmlConstants.HttpQueryStringSelect, targetResourceType.FullName)); } } return boundSegments; }
public void TargetEdmTypeIsTargetType() { TypeSegment typeSegment = new TypeSegment(HardCodedTestModel.GetPersonType(), null); typeSegment.TargetEdmType.Should().BeSameAs(HardCodedTestModel.GetPersonType()); }
private void AddTypeCastsIfNecessary() { IEdmEntityType owningType = null; List<ODataPathSegment> newSegments = new List<ODataPathSegment>(); foreach (ODataPathSegment segment in _segments) { NavigationPropertySegment navProp = segment as NavigationPropertySegment; if (navProp != null && owningType != null && owningType.FindProperty(navProp.NavigationProperty.Name) == null) { // need a type cast TypeSegment typeCast = new TypeSegment( navProp.NavigationProperty.DeclaringType, navigationSource: null); newSegments.Add(typeCast); } newSegments.Add(segment); IEdmEntityType targetEntityType = GetTargetEntityType(segment); if (targetEntityType != null) { owningType = targetEntityType; } } _segments = newSegments; }
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); }