/// <summary> /// Initializes a new instance of the <see cref="CastPathSegment" /> class. /// </summary> /// <param name="previous">The previous segment in the path.</param> /// <param name="castType">The type of the cast.</param> public CastPathSegment(ODataPathSegment previous, IEdmEntityType castType) : base(previous) { if (castType == null) { throw Error.ArgumentNull("cast"); } IEdmType previousEdmType = previous.EdmType; if (previousEdmType == null) { throw Error.InvalidOperation(SRResources.PreviousSegmentEdmTypeCannotBeNull); } if (previousEdmType.TypeKind == EdmTypeKind.Collection) { EdmType = castType.GetCollection(); } else { EdmType = castType; } EntitySet = previous.EntitySet; CastType = castType; }
protected override ODataPathSegment ParseAtEntityCollection(IEdmModel model, ODataPathSegment previous, IEdmType previousEdmType, string segment) { if (segment == "$count") { return new CountPathSegment(); } return base.ParseAtEntityCollection(model, previous, previousEdmType, segment); }
/// <summary> /// Initializes a new instance of the <see cref="ODataPathSegment" /> class. /// </summary> /// <param name="previous">The previous segment in the path.</param> protected ODataPathSegment(ODataPathSegment previous) { if (previous == null) { throw Error.ArgumentNull("previous"); } Previous = previous; }
/// <inheritdoc /> public override bool TryMatch(ODataPathSegment pathSegment, IDictionary<string, object> values) { if (pathSegment.SegmentKind == ODataSegmentKinds.Function) { FunctionPathSegment functionSegment = (FunctionPathSegment)pathSegment; return KeyValuePathSegmentTemplate.TryMatch(ParameterMappings, functionSegment.Values, values); } return false; }
/// <inheritdoc /> public override bool TryMatch(ODataPathSegment pathSegment, IDictionary<string, object> values) { if (pathSegment.SegmentKind == ODataSegmentKinds.Key) { KeyValuePathSegment keySegment = (KeyValuePathSegment)pathSegment; return TryMatch(ParameterMappings, keySegment.Values, values); } return false; }
/// <summary> /// Initializes a new instance of the <see cref="ActionPathSegment" /> class. /// </summary> /// <param name="previous">The previous segment in the path.</param> /// <param name="action">The action being invoked.</param> public ActionPathSegment(ODataPathSegment previous, IEdmFunctionImport action) : base(previous) { if (action == null) { throw Error.ArgumentNull("action"); } Initialize(action); }
/// <summary> /// Initializes a new instance of the <see cref="EntitySetPathSegment" /> class. /// </summary> /// <param name="previous">The previous segment in the path.</param> /// <param name="entitySet">The entity set being accessed.</param> public EntitySetPathSegment(ODataPathSegment previous, IEdmEntitySet entitySet) : base(previous) { if (entitySet == null) { throw Error.ArgumentNull("entitySet"); } EdmType = entitySet.ElementType.GetCollection(); EntitySet = entitySet; }
/// <summary> /// Initializes a new instance of the <see cref="PropertyAccessPathSegment" /> class. /// </summary> /// <param name="previous">The previous segment in the path.</param> /// <param name="property">The property being accessed by this segment.</param> public PropertyAccessPathSegment(ODataPathSegment previous, IEdmProperty property) : base(previous) { if (property == null) { throw Error.ArgumentNull("property"); } EdmType = property.Type.Definition; Property = property; }
protected override ODataPathSegment ParseAtEntityCollection(IEdmModel model, ODataPathSegment previous, IEdmType previousEdmType, string segment) { try { return base.ParseAtEntityCollection(model, previous, previousEdmType, segment); } catch (ODataException) { return new KeyValuePathSegment(segment); } }
/// <summary> /// Initializes a new instance of the <see cref="ActionPathSegment" /> class. /// </summary> /// <param name="previous">The previous segment in the path.</param> /// <param name="action">The action being invoked.</param> public ActionPathSegment(ODataPathSegment previous, IEdmFunctionImport action) : base(previous) { if (action == null) { throw Error.ArgumentNull("action"); } IEdmTypeReference returnType = action.ReturnType; EdmType = returnType == null ? null : returnType.Definition; IEdmEntitySet functionEntitySet = null; if (action.TryGetStaticEntitySet(out functionEntitySet)) { EntitySet = functionEntitySet; } Action = action; }
/// <summary> /// Initializes a new instance of the <see cref="NavigationPathSegment" /> class. /// </summary> /// <param name="previous">The property being accessed by this segment.</param> /// <param name="navigationProperty">The navigation property being accessed by this segment.</param> public NavigationPathSegment(ODataPathSegment previous, IEdmNavigationProperty navigationProperty) : base(previous) { if (navigationProperty == null) { throw Error.ArgumentNull("navigation"); } if (previous.EntitySet == null) { throw Error.Argument(SRResources.PreviousSegmentMustHaveEntitySet); } EdmType = navigationProperty.Partner.Multiplicity() == EdmMultiplicity.Many ? (IEdmType)navigationProperty.ToEntityType().GetCollection() : (IEdmType)navigationProperty.ToEntityType(); EntitySet = previous.EntitySet.FindNavigationTarget(navigationProperty); NavigationProperty = navigationProperty; }
/// <summary> /// Parses the next OData path segment. /// </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 ParseNextSegment(IEdmModel model, ODataPathSegment previous, IEdmType previousEdmType, string segment, Queue<string> segments) { if (String.IsNullOrEmpty(segment)) { throw Error.Argument(SRResources.SegmentNullOrEmpty); } if (previous == null) { // Parse entry node return ParseEntrySegment(model, segment, segments); } else { // Parse non-entry node if (previousEdmType == null) { throw new ODataException(Error.Format(SRResources.InvalidPathSegment, segment, previous)); } switch (previousEdmType.TypeKind) { case EdmTypeKind.Collection: return ParseAtCollection(model, previous, previousEdmType, segment, segments); case EdmTypeKind.Entity: return ParseAtEntity(model, previous, previousEdmType, segment, segments); case EdmTypeKind.Complex: return ParseAtComplex(model, previous, previousEdmType, segment, segments); case EdmTypeKind.Primitive: return ParseAtPrimitiveProperty(model, previous, previousEdmType, segment, segments); default: throw new ODataException(Error.Format(SRResources.InvalidPathSegment, segment, previous)); } } }
/// <inheritdoc /> public override bool TryMatch(ODataPathSegment pathSegment, IDictionary<string, object> values) { if (pathSegment.SegmentKind == ODataSegmentKinds.Function) { FunctionPathSegment functionSegment = (FunctionPathSegment)pathSegment; return functionSegment.Function == Function && functionSegment.FunctionName == FunctionName; } return false; }
/// <inheritdoc/> public override bool TryMatch(ODataPathSegment pathSegment, IDictionary<string, object> values) { return pathSegment.SegmentKind == ODataSegmentKinds.Value; }
/// <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> /// <returns>A parsed representation of the segment.</returns> protected virtual ODataPathSegment ParseAtEntity(IEdmModel model, ODataPathSegment previous, IEdmType previousEdmType, string segment) { if (previous == null) { throw Error.ArgumentNull("previous"); } if (String.IsNullOrEmpty(segment)) { throw Error.Argument(SRResources.SegmentNullOrEmpty); } IEdmEntityType previousType = previousEdmType as IEdmEntityType; if (previousType == null) { throw Error.Argument(SRResources.PreviousSegmentMustBeEntityType, previousEdmType); } if (segment == ODataSegmentKinds.Links) { return(new LinksPathSegment()); } // 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)); } // finally look for bindable procedures IEdmEntityContainer container = ExtractEntityContainer(model); IEdmFunctionImport procedure = container.FunctionImports().FindBindableAction(previousType, segment); if (procedure != null) { return(new ActionPathSegment(procedure)); } // 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); } if (segment == ODataSegmentKinds.Links) { return new LinksPathSegment(); } // 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); } // finally look for bindable procedures IEdmEntityContainer container = ExtractEntityContainer(model); IEdmActionImport action = container.FindAction(segment, previousType); if (action != null) { return new ActionPathSegment(action); } // Try to match this to a function call FunctionPathSegment pathSegment = TryMatchFunctionCall(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); } // now look for bindable actions IEdmEntityContainer container = ExtractEntityContainer(model); IEdmActionImport action = container.FindAction(segment, collectionType); if (action != null) { return new ActionPathSegment(action); } // Try to match this to a function call FunctionPathSegment pathSegment = TryMatchFunctionCall(segment, segments, model, bindingType: collectionType); if (pathSegment != null) { return pathSegment; } throw new ODataException(Error.Format(SRResources.NoActionFoundForCollection, segment, collectionType.ElementType)); }
/// <inheritdoc/> public override bool TryMatch(ODataPathSegment pathSegment, IDictionary<string, object> values) { if (pathSegment.SegmentKind == ODataSegmentKinds.Cast) { CastPathSegment castSegment = (CastPathSegment)pathSegment; return castSegment.CastType == CastType && castSegment.CastTypeName == CastTypeName; } return false; }
/// <inheritdoc/> public override bool TryMatch(ODataPathSegment pathSegment, IDictionary<string, object> values) { if (pathSegment.SegmentKind == ODataSegmentKinds.Navigation) { NavigationPathSegment navigationSegment = (NavigationPathSegment)pathSegment; return navigationSegment.NavigationProperty == NavigationProperty && navigationSegment.NavigationPropertyName == NavigationPropertyName; } return false; }
/// <inheritdoc/> public override bool TryMatch(ODataPathSegment pathSegment, IDictionary<string, object> values) { return false; }
/// <inheritdoc/> public override bool TryMatch(ODataPathSegment pathSegment, IDictionary<string, object> values) { if (pathSegment.SegmentKind == ODataSegmentKinds.EntitySet) { EntitySetPathSegment entitySetSegment = (EntitySetPathSegment)pathSegment; return entitySetSegment.EntitySet == EntitySet && entitySetSegment.EntitySetName == EntitySetName; } return false; }
/// <summary> /// Parses the next OData path segment following a 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 ParseAtCollection(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 collection = previousEdmType as IEdmCollectionType; if (collection == null) { throw Error.Argument(SRResources.PreviousSegmentMustBeCollectionType, previousEdmType); } switch (collection.ElementType.Definition.TypeKind) { case EdmTypeKind.Entity: return ParseAtEntityCollection(model, previous, previousEdmType, segment, segments); default: throw new ODataException(Error.Format(SRResources.InvalidPathSegment, segment, previous)); } }
/// <summary> /// Parses the first OData segment following the service base URI. /// </summary> /// <param name="root">The service base path segment.</param> /// <param name="segment">The value of the segment to parse.</param> /// <returns>A parsed representation of the segment.</returns> protected virtual ODataPathSegment ParseEntrySegment(ODataPathSegment root, string segment) { if (root == null) { throw Error.ArgumentNull("root"); } if (String.IsNullOrEmpty(segment)) { throw Error.Argument(SRResources.SegmentNullOrEmpty); } if (segment == ODataSegmentKinds.Metadata) { return new MetadataPathSegment(root); } if (segment == ODataSegmentKinds.Batch) { return new BatchPathSegment(root); } IEdmEntitySet entitySet = Container.FindEntitySet(segment); if (entitySet != null) { return new EntitySetPathSegment(root, entitySet); } IEdmFunctionImport function = Container.FunctionImports().SingleOrDefault(fi => fi.Name == segment && fi.IsBindable == false); if (function != null) { return new ActionPathSegment(root, function); } // segment does not match the model return null; }
/// <summary> /// Parses the next OData path segment following a complex-typed segment. /// </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 ParseAtComplex(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); } IEdmComplexType previousType = previousEdmType as IEdmComplexType; if (previousType == null) { throw Error.Argument(SRResources.PreviousSegmentMustBeComplexType, previousEdmType); } // look for properties IEdmProperty property = previousType.Properties().SingleOrDefault(p => p.Name == segment); if (property != null) { return new PropertyAccessPathSegment(property); } // Treating as an open property return new UnresolvedPathSegment(segment); }
/// <summary> /// Parses the next OData path segment following an entity collection. /// </summary> /// <param name="previous">The previous path segment.</param> /// <param name="segment">The value of the segment to parse.</param> /// <returns>A parsed representation of the segment.</returns> protected virtual ODataPathSegment ParseAtEntityCollection(ODataPathSegment previous, string segment) { if (previous == null) { throw Error.ArgumentNull("previous"); } if (String.IsNullOrEmpty(segment)) { throw Error.Argument(SRResources.SegmentNullOrEmpty); } if (previous.EdmType == null) { throw Error.InvalidOperation(SRResources.PreviousSegmentEdmTypeCannotBeNull); } IEdmCollectionType collectionType = previous.EdmType as IEdmCollectionType; if (collectionType == null) { throw Error.Argument(SRResources.PreviousSegmentMustBeEntityCollectionType, previous.EdmType); } IEdmEntityType elementType = collectionType.ElementType.Definition as IEdmEntityType; if (elementType == null) { throw Error.Argument(SRResources.PreviousSegmentMustBeEntityCollectionType, previous.EdmType); } // 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(previous, value); } // next look for casts IEdmEntityType castType = Model.FindDeclaredType(segment) as IEdmEntityType; if (castType != null) { IEdmType previousElementType = collectionType.ElementType.Definition; if (!castType.IsOrInheritsFrom(previousElementType)) { throw new ODataException(Error.Format(SRResources.InvalidCastInPath, castType, previousElementType)); } return new CastPathSegment(previous, castType); } // now look for bindable actions IEdmFunctionImport procedure = Container.FunctionImports().FindBindableAction(collectionType, segment); if (procedure != null) { return new ActionPathSegment(previous, procedure); } throw new ODataException(Error.Format(SRResources.NoActionFoundForCollection, segment, collectionType.ElementType)); }
/// <summary> /// Parses the next OData path segment following a primitive property. /// </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 ParseAtPrimitiveProperty(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 (segment == ODataSegmentKinds.Value) { return new ValuePathSegment(); } throw new ODataException(Error.Format(SRResources.InvalidPathSegment, segment, previous)); }
/// <summary> /// Parses the next OData path segment following an entity. /// </summary> /// <param name="previous">The previous path segment.</param> /// <param name="segment">The value of the segment to parse.</param> /// <returns>A parsed representation of the segment.</returns> protected virtual ODataPathSegment ParseAtEntity(ODataPathSegment previous, string segment) { if (previous == null) { throw Error.ArgumentNull("previous"); } if (String.IsNullOrEmpty(segment)) { throw Error.Argument(SRResources.SegmentNullOrEmpty); } IEdmEntityType previousType = previous.EdmType as IEdmEntityType; if (previousType == null) { throw Error.Argument(SRResources.PreviousSegmentMustBeEntityType, previous.EdmType); } if (segment == ODataSegmentKinds.Links) { return new LinksPathSegment(previous); } // first look for navigation properties IEdmNavigationProperty navigation = previousType.NavigationProperties().SingleOrDefault(np => np.Name == segment); if (navigation != null) { return new NavigationPathSegment(previous, navigation); } // next look for properties IEdmProperty property = previousType.Properties().SingleOrDefault(p => p.Name == segment); if (property != null) { return new PropertyAccessPathSegment(previous, property); } // next look for type casts IEdmEntityType castType = Model.FindDeclaredType(segment) as IEdmEntityType; if (castType != null) { if (!castType.IsOrInheritsFrom(previousType)) { throw new ODataException(Error.Format(SRResources.InvalidCastInPath, castType, previousType)); } return new CastPathSegment(previous, castType); } // finally look for bindable procedures IEdmFunctionImport procedure = Container.FunctionImports().FindBindableAction(previousType, segment); if (procedure != null) { return new ActionPathSegment(previous, procedure); } // Treating as an open property return new UnresolvedPathSegment(previous, segment); }
/// <inheritdoc/> public override bool TryMatch(ODataPathSegment pathSegment, IDictionary<string, object> values) { if (pathSegment.SegmentKind == ODataSegmentKinds.Property) { PropertyAccessPathSegment propertySegment = (PropertyAccessPathSegment)pathSegment; return propertySegment.Property == Property && propertySegment.PropertyName == PropertyName; } return false; }
/// <inheritdoc/> public override bool TryMatch(ODataPathSegment pathSegment, IDictionary<string, object> values) { if (pathSegment.SegmentKind == ODataSegmentKinds.Action) { ActionPathSegment actionSegment = (ActionPathSegment)pathSegment; return actionSegment.Action == Action && actionSegment.ActionName == ActionName; } return false; }