/// <summary> /// Parses the next OData path segment following an entity. /// </summary> /// <param name="model">The model to use for path parsing.</param> /// <param name="previous">The previous path segment.</param> /// <param name="previousEdmType">The EDM type of the OData path up to the previous segment.</param> /// <param name="segment">The value of the segment to parse.</param> /// <param name="segments">The queue of pending segments.</param> /// <returns>A parsed representation of the segment.</returns> protected virtual ODataPathSegment ParseAtEntity(IEdmModel model, ODataPathSegment previous, IEdmType previousEdmType, string segment, Queue<string> segments) { if (previous == null) { throw Error.ArgumentNull("previous"); } if (segments == null) { throw Error.ArgumentNull("segments"); } if (String.IsNullOrEmpty(segment)) { throw Error.Argument(SRResources.SegmentNullOrEmpty); } IEdmEntityType previousType = previousEdmType as IEdmEntityType; if (previousType == null) { throw Error.Argument(SRResources.PreviousSegmentMustBeEntityType, previousEdmType); } // first look for navigation properties IEdmNavigationProperty navigation = previousType.NavigationProperties().SingleOrDefault(np => np.Name == segment); if (navigation != null) { return new NavigationPathSegment(navigation); } // next look for properties IEdmProperty property = previousType.Properties().SingleOrDefault(p => p.Name == segment); if (property != null) { return new PropertyAccessPathSegment(property); } // next look for type casts IEdmEntityType castType = model.FindDeclaredType(segment) as IEdmEntityType; if (castType != null) { if (!castType.IsOrInheritsFrom(previousType) && !previousType.IsOrInheritsFrom(castType)) { throw new ODataException(Error.Format(SRResources.InvalidCastInPath, castType, previousType)); } return new CastPathSegment(castType); } // look for $ref if (segment == ODataSegmentKinds.Ref) { return new RefPathSegment(); } // finally look for bindable procedures IEdmAction action = model.FindAction(segment, previousType); if (action != null) { return new BoundActionPathSegment(action); } // Try to match this to a function call BoundFunctionPathSegment pathSegment = TryMatchBoundFunctionCall(segment, segments, model, bindingType: previousType); if (pathSegment != null) { return pathSegment; } // Treating as an open property return new UnresolvedPathSegment(segment); }
/// <summary> /// Parses the next OData path segment following an entity. /// </summary> /// <param name="model">The model to use for path parsing.</param> /// <param name="previous">The previous path segment.</param> /// <param name="previousEdmType">The EDM type of the OData path up to the previous segment.</param> /// <param name="segment">The value of the segment to parse.</param> /// <param name="segments">The queue of pending segments.</param> /// <returns>A parsed representation of the segment.</returns> protected virtual ODataPathSegment ParseAtEntity(IEdmModel model, ODataPathSegment previous, IEdmType previousEdmType, string segment, Queue <string> segments) { if (previous == null) { throw Error.ArgumentNull("previous"); } if (segments == null) { throw Error.ArgumentNull("segments"); } if (String.IsNullOrEmpty(segment)) { throw Error.Argument(SRResources.SegmentNullOrEmpty); } IEdmEntityType previousType = previousEdmType as IEdmEntityType; if (previousType == null) { throw Error.Argument(SRResources.PreviousSegmentMustBeEntityType, previousEdmType); } // first look for navigation properties IEdmNavigationProperty navigation = previousType.NavigationProperties().SingleOrDefault(np => np.Name == segment); if (navigation != null) { return(new NavigationPathSegment(navigation)); } // next look for properties IEdmProperty property = previousType.Properties().SingleOrDefault(p => p.Name == segment); if (property != null) { return(new PropertyAccessPathSegment(property)); } // next look for type casts IEdmEntityType castType = model.FindDeclaredType(segment) as IEdmEntityType; if (castType != null) { if (!castType.IsOrInheritsFrom(previousType) && !previousType.IsOrInheritsFrom(castType)) { throw new ODataException(Error.Format(SRResources.InvalidCastInPath, castType, previousType)); } return(new CastPathSegment(castType)); } // look for $ref if (segment == ODataSegmentKinds.Ref) { return(new RefPathSegment()); } // finally look for bindable procedures IEdmAction action = model.FindAction(segment, previousType); if (action != null) { return(new BoundActionPathSegment(action)); } // Try to match this to a function call BoundFunctionPathSegment pathSegment = TryMatchBoundFunctionCall(segment, segments, model, bindingType: previousType); if (pathSegment != null) { return(pathSegment); } // Treating as an open property return(new UnresolvedPathSegment(segment)); }
/// <summary> /// Parses the next OData path segment following an entity collection. /// </summary> /// <param name="model">The model to use for path parsing.</param> /// <param name="previous">The previous path segment.</param> /// <param name="previousEdmType">The EDM type of the OData path up to the previous segment.</param> /// <param name="segment">The value of the segment to parse.</param> /// <param name="segments">The queue of pending segments.</param> /// <returns>A parsed representation of the segment.</returns> protected virtual ODataPathSegment ParseAtEntityCollection(IEdmModel model, ODataPathSegment previous, IEdmType previousEdmType, string segment, Queue<string> segments) { if (previous == null) { throw Error.ArgumentNull("previous"); } if (segments == null) { throw Error.ArgumentNull("segments"); } if (String.IsNullOrEmpty(segment)) { throw Error.Argument(SRResources.SegmentNullOrEmpty); } if (previousEdmType == null) { throw Error.InvalidOperation(SRResources.PreviousSegmentEdmTypeCannotBeNull); } IEdmCollectionType collectionType = previousEdmType as IEdmCollectionType; if (collectionType == null) { throw Error.Argument(SRResources.PreviousSegmentMustBeEntityCollectionType, previousEdmType); } IEdmEntityType elementType = collectionType.ElementType.Definition as IEdmEntityType; if (elementType == null) { throw Error.Argument(SRResources.PreviousSegmentMustBeEntityCollectionType, previousEdmType); } // look for keys first. if (segment.StartsWith("(", StringComparison.Ordinal) && segment.EndsWith(")", StringComparison.Ordinal)) { Contract.Assert(segment.Length >= 2); string value = segment.Substring(1, segment.Length - 2); return new KeyValuePathSegment(value); } // next look for casts IEdmEntityType castType = model.FindDeclaredType(segment) as IEdmEntityType; if (castType != null) { IEdmType previousElementType = collectionType.ElementType.Definition; if (!castType.IsOrInheritsFrom(previousElementType) && !previousElementType.IsOrInheritsFrom(castType)) { throw new ODataException(Error.Format(SRResources.InvalidCastInPath, castType, previousElementType)); } return new CastPathSegment(castType); } // look for $ref if (segment == ODataSegmentKinds.Ref) { return new RefPathSegment(); } // now look for bindable actions IEdmAction action = model.FindAction(segment, collectionType); if (action != null) { return new BoundActionPathSegment(action); } // Try to match this to a function call BoundFunctionPathSegment pathSegment = TryMatchBoundFunctionCall(segment, segments, model, bindingType: collectionType); if (pathSegment != null) { return pathSegment; } throw new ODataException(Error.Format(SRResources.NoActionFoundForCollection, segment, collectionType.ElementType)); }
/// <summary> /// Parses the next OData path segment following an entity collection. /// </summary> /// <param name="model">The model to use for path parsing.</param> /// <param name="previous">The previous path segment.</param> /// <param name="previousEdmType">The EDM type of the OData path up to the previous segment.</param> /// <param name="segment">The value of the segment to parse.</param> /// <param name="segments">The queue of pending segments.</param> /// <returns>A parsed representation of the segment.</returns> protected virtual ODataPathSegment ParseAtEntityCollection(IEdmModel model, ODataPathSegment previous, IEdmType previousEdmType, string segment, Queue <string> segments) { if (previous == null) { throw Error.ArgumentNull("previous"); } if (segments == null) { throw Error.ArgumentNull("segments"); } if (String.IsNullOrEmpty(segment)) { throw Error.Argument(SRResources.SegmentNullOrEmpty); } if (previousEdmType == null) { throw Error.InvalidOperation(SRResources.PreviousSegmentEdmTypeCannotBeNull); } IEdmCollectionType collectionType = previousEdmType as IEdmCollectionType; if (collectionType == null) { throw Error.Argument(SRResources.PreviousSegmentMustBeEntityCollectionType, previousEdmType); } IEdmEntityType elementType = collectionType.ElementType.Definition as IEdmEntityType; if (elementType == null) { throw Error.Argument(SRResources.PreviousSegmentMustBeEntityCollectionType, previousEdmType); } // look for keys first. if (segment.StartsWith("(", StringComparison.Ordinal) && segment.EndsWith(")", StringComparison.Ordinal)) { Contract.Assert(segment.Length >= 2); string value = segment.Substring(1, segment.Length - 2); return(new KeyValuePathSegment(value)); } // next look for casts IEdmEntityType castType = model.FindDeclaredType(segment) as IEdmEntityType; if (castType != null) { IEdmType previousElementType = collectionType.ElementType.Definition; if (!castType.IsOrInheritsFrom(previousElementType) && !previousElementType.IsOrInheritsFrom(castType)) { throw new ODataException(Error.Format(SRResources.InvalidCastInPath, castType, previousElementType)); } return(new CastPathSegment(castType)); } // look for $ref if (segment == ODataSegmentKinds.Ref) { return(new RefPathSegment()); } // now look for bindable actions IEdmAction action = model.FindAction(segment, collectionType); if (action != null) { return(new BoundActionPathSegment(action)); } // Try to match this to a function call BoundFunctionPathSegment pathSegment = TryMatchBoundFunctionCall(segment, segments, model, bindingType: collectionType); if (pathSegment != null) { return(pathSegment); } throw new ODataException(Error.Format(SRResources.NoActionFoundForCollection, segment, collectionType.ElementType)); }