public override string Translate(OperationSegment segment) { return(string.Format( "{{Operation:[{0}]{1}}}", segment.Operations.First().FullName(), string.Join(",", segment.Parameters.Select(Translate)))); }
public void CtorFunctionSegmentTemplate_SetsProperties() { // Arrange & Act FunctionSegmentTemplate segment = new FunctionSegmentTemplate(_edmFunction, null); // Assert Assert.Same(_edmFunction, segment.Function); Assert.Null(segment.NavigationSource); Assert.Collection(segment.ParameterMappings, e => { Assert.Equal("name", e.Key); Assert.Equal("name", e.Value); }, e => { Assert.Equal("title", e.Key); Assert.Equal("title", e.Value); }); // Arrange OperationSegment operationSegment = new OperationSegment(_edmFunction, null); // Act segment = new FunctionSegmentTemplate(operationSegment); // Assert Assert.Same(_edmFunction, segment.Function); Assert.Null(segment.NavigationSource); }
private static bool TryBindAsOperation(PathSegmentToken pathToken, IEdmModel model, IEdmEntityType entityType, out ODataPathSegment segment) { Debug.Assert(pathToken != null, "pathToken != null"); Debug.Assert(entityType != null, "bindingType != null"); IEnumerable <IEdmFunctionImport> functionImports; var resolver = model as IODataUriParserModelExtensions; if (resolver != null) { functionImports = resolver.FindFunctionImportsByBindingParameterTypeHierarchy(entityType, pathToken.Identifier); } else { functionImports = model.FindFunctionImportsByBindingParameterTypeHierarchy(entityType, pathToken.Identifier); } List <IEdmFunctionImport> possibleFunctions = functionImports.ToList(); if (possibleFunctions.Count <= 0) { segment = null; return(false); } segment = new OperationSegment(possibleFunctions, null /*entitySet*/); return(true); }
private static string GetRootElementName(ODataPath path) { if (path != null) { ODataPathSegment lastSegment = path.Segments.LastOrDefault(); if (lastSegment != null) { OperationSegment actionSegment = lastSegment as OperationSegment; if (actionSegment != null) { IEdmAction action = actionSegment.Operations.Single() as IEdmAction; if (action != null) { return(action.Name); } } PropertySegment propertyAccessSegment = lastSegment as PropertySegment; if (propertyAccessSegment != null) { return(propertyAccessSegment.Property.Name); } } } return(null); }
private static Microsoft.OData.UriParser.ODataPath ConvertPath(ODataPath path) { if (path == null) { return(null); } if (IsOperationPath(path)) { var lastSegment = path.Segments.Last(); OperationSegment operation = lastSegment as OperationSegment; if (operation != null && operation.EntitySet != null) { return(GeneratePath(operation.EntitySet)); } OperationImportSegment operationImport = lastSegment as OperationImportSegment; if (operationImport != null && operationImport.EntitySet != null) { return(GeneratePath(operationImport.EntitySet)); } return(null); } return(path.Path); }
public void TryTranslateFunctionImportSegmentTemplate_ReturnsTemplates_ForEmptyParameter() { // Arrange EdmModel edmModel = new EdmModel(); EdmFunction function = new EdmFunction("NS", "MyFunction", IntType, true, null, false); function.AddParameter("bindingParameter", IntType); edmModel.AddElement(function); FunctionSegmentTemplate template = new FunctionSegmentTemplate(function, null); ODataTemplateTranslateContext context = new ODataTemplateTranslateContext { RouteValues = new RouteValueDictionary(), Model = edmModel }; // Act bool ok = template.TryTranslate(context); // Assert Assert.True(ok); ODataPathSegment actual = Assert.Single(context.Segments); OperationSegment functionSegment = Assert.IsType <OperationSegment>(actual); Assert.Same(function, functionSegment.Operations.First()); Assert.Empty(functionSegment.Parameters); }
public void DuplicatedSelectPathInOneDollarSelectWorksAsSingle(string select, string expect) { // Arrange ODataQueryOptionParser parser = new ODataQueryOptionParser(_model.Model, _model.Customer, _model.Customers, new Dictionary <string, string> { { "$select", select } }); // Act SelectExpandClause selectAndExpand = parser.ParseSelectAndExpand(); // Assert Assert.NotNull(selectAndExpand); Assert.False(selectAndExpand.AllSelected); SelectItem selectItem = Assert.Single(selectAndExpand.SelectedItems); PathSelectItem pathSelectItem = Assert.IsType <PathSelectItem>(selectItem); ODataPathSegment pathSegment = Assert.Single(pathSelectItem.SelectedPath); if (expect == "ID") { PropertySegment propertySegment = Assert.IsType <PropertySegment>(pathSegment); Assert.Equal(expect, propertySegment.Identifier); } else { OperationSegment operationSegment = Assert.IsType <OperationSegment>(pathSegment); Assert.Equal(expect, operationSegment.Operations.Single().FullName()); } }
internal static Uri GenerateActionLink(this ResourceContext resourceContext, IEdmTypeReference bindingParameterType, IEdmOperation action) { Contract.Assert(resourceContext != null); if (resourceContext.NavigationSource is IEdmContainedEntitySet) { return(null); } IList <ODataPathSegment> actionPathSegments = resourceContext.GenerateBaseODataPathSegments(); // generate link with cast if the navigation source doesn't match the entity type the action is bound to. if (resourceContext.NavigationSource.EntityType() != bindingParameterType.Definition) { actionPathSegments.Add(new TypeSegment((IEdmEntityType)bindingParameterType.Definition, null)); // entity set can be null } OperationSegment operationSegment = new OperationSegment(new[] { action }, null); actionPathSegments.Add(operationSegment); string actionLink = resourceContext.InternalUrlHelper.CreateODataLink(actionPathSegments); return(actionLink == null ? null : new Uri(actionLink)); }
/// <summary> /// Initializes a new instance of the <see cref="FunctionSegmentTemplate" /> class. /// </summary> /// <param name="operationSegment">The operation segment, it should be a function segment and the parameters are template.</param> public FunctionSegmentTemplate(OperationSegment operationSegment) { if (operationSegment == null) { throw Error.ArgumentNull(nameof(operationSegment)); } IEdmOperation operation = operationSegment.Operations.FirstOrDefault(); if (!operation.IsFunction()) { throw new ODataException(Error.Format(SRResources.SegmentShouldBeKind, "Function", "FunctionSegmentTemplate")); } Function = (IEdmFunction)operation; NavigationSource = operationSegment.EntitySet; ParameterMappings = OperationHelper.BuildParameterMappings(operationSegment.Parameters, operation.FullName()); // Join the parameters as p1={p1} string parameterStr = "(" + string.Join(",", ParameterMappings.Select(a => $"{a.Key}={{{a.Value}}}")) + ")"; UnqualifiedIdentifier = Function.Name + parameterStr; Literal = Function.FullName() + parameterStr; // Function will always have the return type IsSingle = Function.ReturnType.TypeKind() != EdmTypeKind.Collection; HasOptionalMissing = ParameterMappings.Count != Function.Parameters.Count() - 1; }
/// <summary> /// Handle an OperationSegment /// </summary> /// <param name="segment">the segment to handle</param> public override void Handle(OperationSegment segment) { Contract.Assert(segment != null); NavigationSource = segment.EntitySet; IEdmAction action = segment.Operations.Single() as IEdmAction; if (action != null) { _path.Add(action.FullName()); } else { IEdmFunction function = (IEdmFunction)segment.Operations.Single(); IList <string> parameterValues = new List <string>(); foreach (var parameter in segment.Parameters) { var functionParameter = function.Parameters.FirstOrDefault(p => p.Name == parameter.Name); if (functionParameter == null) { continue; } parameterValues.Add(functionParameter.Type.FullName()); } string literal = string.Format(CultureInfo.InvariantCulture, "{0}({1})", function.FullName(), string.Join(",", parameterValues)); _path.Add(literal); } }
internal static Uri GenerateFunctionLink(this ResourceContext resourceContext, IEdmTypeReference bindingParameterType, IEdmOperation function, IEnumerable <string> parameterNames) { IList <ODataPathSegment> functionPathSegments = resourceContext.GenerateBaseODataPathSegments(); // generate link with cast if the navigation source type doesn't match the entity type the function is bound to. if (resourceContext.NavigationSource.EntityType() != bindingParameterType.Definition) { functionPathSegments.Add(new TypeSegment(bindingParameterType.Definition, null)); } IList <OperationSegmentParameter> parameters = new List <OperationSegmentParameter>(); // skip the binding parameter foreach (string param in parameterNames.Skip(1)) { string value = "@" + param; parameters.Add(new OperationSegmentParameter(param, new ConstantNode(value, value))); } OperationSegment segment = new OperationSegment(new[] { function }, parameters, null); functionPathSegments.Add(segment); string functionLink = resourceContext.InternalUrlHelper.CreateODataLink(functionPathSegments); return(functionLink == null ? null : new Uri(functionLink)); }
private void AddOperations(OperationSegment operationSegment, ISet <IEdmAction> allActions, ISet <IEdmFunction> allFunctions) { foreach (IEdmOperation operation in operationSegment.Operations) { IEdmAction action = operation as IEdmAction; if (action != null && allActions.Contains(action)) { if (SelectedActions == null) { SelectedActions = new HashSet <IEdmAction>(); } SelectedActions.Add(action); } IEdmFunction function = operation as IEdmFunction; if (function != null && allFunctions.Contains(function)) { if (SelectedFunctions == null) { SelectedFunctions = new HashSet <IEdmFunction>(); } SelectedFunctions.Add(function); } } }
public async Task VisitAsync(ODataPath path) { NotFound = false; BadRequest = false; Result = null; ResultType = null; PropertySetter = null; Index = 0; foreach (var segment in path) { await(segment switch { TypeSegment typeSegment => VisitAsync(typeSegment), NavigationPropertySegment navigationPropertySegment => VisitAsync(navigationPropertySegment), EntitySetSegment entitySetSegment => VisitAsync(entitySetSegment), SingletonSegment singletonSegment => VisitAsync(singletonSegment), KeySegment keySegment => VisitAsync(keySegment), PropertySegment propertySegment => VisitAsync(propertySegment), AnnotationSegment annotationSegment => VisitAsync(annotationSegment), OperationImportSegment operationImportSegment => VisitAsync(operationImportSegment), OperationSegment operationSegment => VisitAsync(operationSegment), DynamicPathSegment dynamicPathSegment => VisitAsync(dynamicPathSegment), CountSegment countSegment => VisitAsync(countSegment), FilterSegment filterSegment => VisitAsync(filterSegment), ReferenceSegment referenceSegment => VisitAsync(referenceSegment), EachSegment eachSegment => VisitAsync(eachSegment), NavigationPropertyLinkSegment navigationPropertyLinkSegment => VisitAsync(navigationPropertyLinkSegment), ValueSegment valueSegment => VisitAsync(valueSegment), BatchSegment batchSegment => VisitAsync(batchSegment), BatchReferenceSegment batchReferenceSegment => VisitAsync(batchReferenceSegment), MetadataSegment metadataSegment => VisitAsync(metadataSegment), PathTemplateSegment pathTemplateSegment => VisitAsync(pathTemplateSegment), _ => throw new NotSupportedException() });
public void ParseDynamicPathSegmentFunc_ReturnOperationSegment_WithCollectionReturnType_WithCount() { var container = ContainerBuilderHelper.BuildContainer(builder => builder.AddService <UriPathParser, SingleSegmentUriPathParser>(ServiceLifetime.Scoped)); Uri fullUri = new Uri("https://serviceRoot/drives('b!3195njZm9ECS0rQfW5QyZ0iJh-jL7uZGn60CTehSbIwT3VAIax8sRKiyg_aD0HNV')/recent/$count"); var uriParser = new ODataUriParser(oneDriveModel, ServiceRoot, fullUri, container); var operation = oneDriveModel.SchemaElements.OfType <IEdmOperation>().FirstOrDefault(o => o.Name == "recent"); uriParser.ParseDynamicPathSegmentFunc = (previous, identifier, parenthesisExpression) => { switch (identifier) { case "recent": var operationSegment = new OperationSegment(operation, containedItemsNav as IEdmEntitySetBase) { Identifier = identifier }; return(new List <ODataPathSegment> { operationSegment }); default: throw new Exception("Not supported Type"); } }; var path = uriParser.ParsePath(); path.ElementAt(2).ShouldBeOperationSegment(operation); path.LastSegment.ShouldBeCountSegment(); }
private static object GetParameterValue(OperationSegment segment, string paramName) { if (segment == null) { throw Error.ArgumentNull("segment"); } if (string.IsNullOrEmpty(paramName)) { throw Error.ArgumentNullOrEmpty("parameterName"); } if (!segment.Operations.Any() || !segment.Operations.First().IsFunction()) { throw Error.Argument("segment"); } OperationSegmentParameter parameter = segment.Parameters.FirstOrDefault(p => p.Name == paramName); Assert.NotNull(parameter); ConstantNode node = parameter.Value as ConstantNode; if (node != null) { return(node.Value); } return(TranslateNode(parameter.Value)); }
/// <summary> /// Initializes a new instance of the <see cref="FunctionSegmentTemplate" /> class. /// </summary> /// <param name="operationSegment">The operation segment, it should be a function segment and the parameters are template.</param> public FunctionSegmentTemplate(OperationSegment operationSegment) { if (operationSegment == null) { throw Error.ArgumentNull(nameof(operationSegment)); } IEdmOperation operation = operationSegment.Operations.FirstOrDefault(); if (!operation.IsFunction()) { throw new ODataException(Error.Format(SRResources.SegmentShouldBeKind, "Function", "FunctionSegmentTemplate")); } Function = (IEdmFunction)operation; NavigationSource = operationSegment.EntitySet; ParameterMappings = OperationHelper.BuildParameterMappings(operationSegment.Parameters, operation.FullName()); // join the parameters as p1={p1} string routeKey = ParameterMappings.BuildRouteKey(); string parameterStr = ParameterMappings.Count == 0 ? "()" : $"({{{routeKey}}})"; UnqualifiedIdentifier = Function.Name + parameterStr; Literal = Function.FullName() + parameterStr; // Function will always have the return type IsSingle = Function.ReturnType.TypeKind() != EdmTypeKind.Collection; }
public static string ToUriLiteral(this OperationSegment segment) { if (segment == null) { throw Error.ArgumentNull("segment"); } IEdmAction action = segment.Operations.Single() as IEdmAction; if (action != null) { return(action.FullName()); } else { // Translate the nodes in ODL path to string literals as parameter of BoundFunctionPathSegment. Dictionary <string, string> parameterValues = segment.Parameters.ToDictionary( parameterValue => parameterValue.Name, parameterValue => TranslateNode(parameterValue.Value)); IEdmFunction function = (IEdmFunction)segment.Operations.Single(); IEnumerable <string> parameters = parameterValues.Select(v => String.Format(CultureInfo.InvariantCulture, "{0}={1}", v.Key, v.Value)); return(String.Format(CultureInfo.InvariantCulture, "{0}({1})", function.FullName(), String.Join(",", parameters))); } }
internal static Uri GenerateActionLink(this ResourceSetContext resourceSetContext, IEdmTypeReference bindingParameterType, IEdmOperation action) { Contract.Assert(resourceSetContext != null); if (resourceSetContext.EntitySetBase is IEdmContainedEntitySet) { return(null); } IList <ODataPathSegment> actionPathSegments = new List <ODataPathSegment>(); resourceSetContext.GenerateBaseODataPathSegmentsForFeed(actionPathSegments); // generate link with cast if the navigation source doesn't match the type the action is bound to. if (resourceSetContext.EntitySetBase.Type.FullTypeName() != bindingParameterType.FullName()) { actionPathSegments.Add(new TypeSegment(bindingParameterType.Definition, resourceSetContext.EntitySetBase)); } OperationSegment operationSegment = new OperationSegment(action, entitySet: null); actionPathSegments.Add(operationSegment); string actionLink = resourceSetContext.InternalUrlHelper.CreateODataLink(actionPathSegments); return(actionLink == null ? null : new Uri(actionLink)); }
/// <summary> /// Handle an OperationSegment /// </summary> /// <param name="segment">the segment to handle</param> public override void Handle(OperationSegment segment) { _navigationSource = segment.EntitySet; IEdmAction action = segment.Operations.Single() as IEdmAction; if (action != null) { _pathTemplate.Add(ODataSegmentKinds.Action); // action _pathUriLiteral.Add(action.FullName()); } else { _pathTemplate.Add(ODataSegmentKinds.Function); // function // Translate the nodes in ODL path to string literals as parameter of BoundFunctionPathSegment. Dictionary <string, string> parameterValues = segment.Parameters.ToDictionary( parameterValue => parameterValue.Name, parameterValue => TranslateNode(parameterValue.Value)); // TODO: refactor the function literal for parameter alias IEdmFunction function = (IEdmFunction)segment.Operations.Single(); IEnumerable <string> parameters = parameterValues.Select(v => String.Format(CultureInfo.InvariantCulture, "{0}={1}", v.Key, v.Value)); string literal = String.Format(CultureInfo.InvariantCulture, "{0}({1})", function.FullName(), String.Join(",", parameters)); _pathUriLiteral.Add(literal); } }
public static OperationSegment ShouldBeOperationSegment(this ODataPathSegment segment, params IEdmOperation[] operations) { Assert.NotNull(segment); OperationSegment operationSegment = Assert.IsType <OperationSegment>(segment); operationSegment.Operations.ContainExactly(operations); return(operationSegment); }
public static AndConstraint <OperationSegment> ShouldBeOperationSegment(this ODataPathSegment segment, params IEdmOperation[] operations) { segment.Should().BeOfType <OperationSegment>(); OperationSegment operationSegment = segment.As <OperationSegment>(); operationSegment.Operations.Should().ContainExactly(operations); return(new AndConstraint <OperationSegment>(operationSegment)); }
/// <summary> /// This is a language agnostic function that looks at a operationSegment and returns a list of parameters needed by the operation. /// If the method is a post, the parameters are sought for in the request body. Otherwise they are sort for in the request url /// </summary> /// <param name="operationSegment">OData OperationSegment representing a Function or action</param> /// <param name="snippetModel">Snippet Model to obtain useful data from</param> /// <param name="collectionSuffix">Suffix to be added to elements that are proved to be members collections</param> /// <param name="isOrderedByOptionalParameters">Flag to show whether the parameters are ordered by the the metadata or optionality of params</param> /// <returns></returns> public static IEnumerable <string> GetParameterListFromOperationSegment(OperationSegment operationSegment, SnippetModel snippetModel, string collectionSuffix = "", bool isOrderedByOptionalParameters = true) { var paramList = new List <string>(); if (snippetModel.Method == HttpMethod.Post) { //read parameters from request body since this is an odata action var parametersProvided = new List <string>(); if (!string.IsNullOrEmpty(snippetModel.RequestBody) && JsonConvert.DeserializeObject(snippetModel.RequestBody) is JObject testObj) { foreach (var(key, _) in testObj) { parametersProvided.Add(key); } } if (isOrderedByOptionalParameters) { //first populate the required parameters var requiredParameters = operationSegment.Operations.First().Parameters.Where(param => !param.Type.IsNullable); paramList = AddValidParameterItemsFromIEdmOperationParameterList(paramList, requiredParameters, parametersProvided, collectionSuffix); //populate the parameters the optional parameters we have from the request var optionalParameters = operationSegment.Operations.First().Parameters.Where(param => param.Type.IsNullable); paramList = AddValidParameterItemsFromIEdmOperationParameterList(paramList, optionalParameters, parametersProvided, collectionSuffix); } else { //use the order from the metadata var parameters = operationSegment.Operations.First().Parameters; paramList = AddValidParameterItemsFromIEdmOperationParameterList(paramList, parameters, parametersProvided, collectionSuffix); } } else { //read parameters from url since this is an odata function foreach (var parameter in operationSegment.Parameters) { switch (parameter.Value) { case ConvertNode convertNode: { if (convertNode.Source is ConstantNode constantNode) { paramList.Add($"\"{constantNode.Value}\""); } break; } case ConstantNode constantNode: paramList.Add(constantNode.LiteralText); break; } } } return(paramList); }
public static OperationSegment ShouldHaveConstantParameter <TValue>(this OperationSegment segment, string name, TValue value) { Assert.NotNull(segment); OperationSegmentParameter parameter = segment.Parameters.SingleOrDefault(p => p.Name == name); Assert.NotNull(parameter); parameter.ShouldBeConstantParameterWithValueType(name, value); return(segment); }
public static OperationSegment ShouldHaveSegmentOfParameterAliasNode(this OperationSegment segment, string name, string alias, IEdmTypeReference typeReference = null) { Assert.NotNull(segment); OperationSegmentParameter parameter = segment.Parameters.SingleOrDefault(p => p.Name == name); Assert.NotNull(parameter); parameter.ShouldHaveParameterAliasNode(name, alias, typeReference); return(segment); }
private static IEdmFunction GetFunction(OperationSegment segment) { if (segment != null) { IEdmFunction function = segment.Operations.First() as IEdmFunction; return(function); } return(null); }
public void CanParse_UnqualifiedBoundAction(string url) { // Arrange IEdmModel model = GetModel(); // Act & Assert OperationSegment operationSegment = Assert.IsType <OperationSegment>( new DefaultODataPathHandler().Parse(model, _serviceRoot, url).Segments.Last()); Assert.Single(operationSegment.Operations); Assert.Equal("Drive", operationSegment.Operations.First().Name); }
public void TryTranslateFunctionSegmentTemplate_ReturnsODataFunctionSegment_WithOptionalParameters() { // Arrange EdmModel model = new EdmModel(); _edmFunction.AddOptionalParameter("min", IntType); _edmFunction.AddOptionalParameter("max", IntType); model.AddElement(_edmFunction); IDictionary <string, string> parameters = new Dictionary <string, string> { { "name", "{nameTemp}" }, { "title", "{titleTemp}" }, { "min", "{minTemp}" }, }; FunctionSegmentTemplate template = new FunctionSegmentTemplate(parameters, _edmFunction, null); RouteValueDictionary routeValues = new RouteValueDictionary(new { nameTemp = "'pt'", titleTemp = "'abc'", minTemp = "42" }); ODataTemplateTranslateContext context = new ODataTemplateTranslateContext { RouteValues = routeValues, Model = model }; // Act bool ok = template.TryTranslate(context); // Assert Assert.True(ok); ODataPathSegment actual = Assert.Single(context.Segments); OperationSegment functionSegment = Assert.IsType <OperationSegment>(actual); Assert.Same(_edmFunction, functionSegment.Operations.First()); Assert.Equal(3, functionSegment.Parameters.Count()); Assert.Collection(functionSegment.Parameters, e => { Assert.Equal("name", e.Name); Assert.Equal("pt", e.Value); }, e => { Assert.Equal("title", e.Name); Assert.Equal("abc", e.Value); }, e => { Assert.Equal("min", e.Name); Assert.Equal(42, e.Value); }); }
public void CtorFunctionSegmentTemplate_ThrowsODataException_NonFunction() { // Arrange IEdmPrimitiveTypeReference intPrimitive = EdmCoreModel.Instance.GetPrimitive(EdmPrimitiveTypeKind.Int32, false); EdmAction action = new EdmAction("NS", "MyAction", intPrimitive); OperationSegment operationSegment = new OperationSegment(action, null); // Act Action test = () => new FunctionSegmentTemplate(operationSegment); // Assert ExceptionAssert.Throws <ODataException>(test, "The input segment should be 'Function' in 'FunctionSegmentTemplate'."); }
/// <summary> /// Initializes a new instance of the <see cref="ActionSegmentTemplate" /> class. /// </summary> /// <param name="action">The Edm action.</param> /// <param name="navigationSource">Unqualified function/action call boolean value.</param> public ActionSegmentTemplate(IEdmAction action, IEdmNavigationSource navigationSource) { Action = action ?? throw Error.ArgumentNull(nameof(action)); NavigationSource = navigationSource; if (action.ReturnType != null) { IsSingle = action.ReturnType.TypeKind() != EdmTypeKind.Collection; EdmType = action.ReturnType.Definition; } Segment = new OperationSegment(Action, NavigationSource as IEdmEntitySetBase); }
private static IEdmAction GetAction(ODataPath odataPath) { ODataPathSegment odataSegment = odataPath.Segments.Last(); IEdmAction action = null; OperationSegment actionSegment = odataSegment as OperationSegment; if (actionSegment != null) { action = actionSegment.Operations.First() as IEdmAction; } return(action); }
public override void Handle(OperationSegment segment) { this.ThrowIfResolved(); this.NavigationSource = segment.EntitySet; this.Property = null; this.Type = segment.EdmType; this.ElementType = this.GetElementType(this.Type); this.IsOperation = true; this.PushParentSegment(); this.childSegments.Add(segment); this.canonicalSegments.Add(segment); }
/// <summary> /// Applies the selection for the given operation segment to the given projection node. /// </summary> /// <param name="operationSegment">The operation segment to apply to the projection node.</param> /// <param name="currentNode">The current projection node.</param> /// <param name="targetResourceType">The target type based on type segments.</param> private static void ApplySelectionForOperations(OperationSegment operationSegment, ExpandedProjectionNode currentNode, ResourceType targetResourceType) { IEnumerable<OperationWrapper> selectedOperations = operationSegment.Operations.Select(f => { var metadataProviderEdmFunctionImport = f as MetadataProviderEdmOperation; Debug.Assert(metadataProviderEdmFunctionImport != null, "metadataProviderEdmFunctionImport != null"); OperationWrapper operation = metadataProviderEdmFunctionImport.ServiceOperation; Debug.Assert(operation != null, "operation != null"); return operation; }); // Note that AddSelectedOperations will return false if the enumerable is empty. bool anyOperations = currentNode.SelectedOperations.AddSelectedOperations(targetResourceType, selectedOperations); Debug.Assert(anyOperations, "Operations segment should not have been created if no operations were found."); }
/// <summary> /// Handle an OperationSegment /// </summary> /// <param name="segment">the segment to Handle</param> public virtual void Handle(OperationSegment segment) { throw new NotImplementedException(); }
public void Translate_OperationSegment_To_BoundActionPathSegment_Works() { // Arrange IEdmEntitySet entityset = _model.FindDeclaredEntitySet("Products"); IEnumerable<IEdmOperation> operations = _model.FindDeclaredOperations("Default.GetProducts"); OperationSegment segment = new OperationSegment(operations, entityset); // Act IEnumerable<ODataPathSegment> segments = _translator.Translate(segment); // Assert ODataPathSegment pathSegment = Assert.Single(segments); BoundActionPathSegment boundActionPathSegment = Assert.IsType<BoundActionPathSegment>(pathSegment); Assert.Same(operations.First(), boundActionPathSegment.Action); }
private void AddOperations(HashSet<IEdmAction> allActions, HashSet<IEdmFunction> allFunctions, OperationSegment operationSegment) { foreach (IEdmOperation operation in operationSegment.Operations) { IEdmAction action = operation as IEdmAction; if (action != null && allActions.Contains(action)) { SelectedActions.Add(action); } IEdmFunction function = operation as IEdmFunction; if (function != null && allFunctions.Contains(function)) { SelectedFunctions.Add(function); } } }
internal static bool TryBindAsOperation(PathSegmentToken pathToken, IEdmModel model, IEdmStructuredType entityType, out ODataPathSegment segment) { Debug.Assert(pathToken != null, "pathToken != null"); Debug.Assert(entityType != null, "bindingType != null"); List<IEdmOperation> possibleFunctions = new List<IEdmOperation>(); // Catch all catchable exceptions as FindDeclaredBoundOperations is implemented by anyone. // If an exception occurs it will be supressed and the possible functions will be empty and return false. try { int wildCardPos = pathToken.Identifier.IndexOf("*", StringComparison.Ordinal); if (wildCardPos > -1) { string namespaceName = pathToken.Identifier.Substring(0, wildCardPos - 1); possibleFunctions = model.FindBoundOperations(entityType).Where(o => o.Namespace == namespaceName).ToList(); } else { NonSystemToken nonSystemToken = pathToken as NonSystemToken; IList<string> parameterNames = new List<string>(); if (nonSystemToken != null && nonSystemToken.NamedValues != null) { parameterNames = nonSystemToken.NamedValues.Select(s => s.Name).ToList(); } if (parameterNames.Count > 0) { // Always force to use fully qualified name when select operation possibleFunctions = model.FindBoundOperations(entityType).FilterByName(true, pathToken.Identifier).FilterOperationsByParameterNames(parameterNames, false).ToList(); } else { possibleFunctions = model.FindBoundOperations(entityType).FilterByName(true, pathToken.Identifier).ToList(); } } } catch (Exception exc) { if (!ExceptionUtils.IsCatchableExceptionType(exc)) { throw; } } possibleFunctions = possibleFunctions.EnsureOperationsBoundWithBindingParameter().ToList(); // Only filter if there is more than one and its needed. if (possibleFunctions.Count > 1) { possibleFunctions = possibleFunctions.FilterBoundOperationsWithSameTypeHierarchyToTypeClosestToBindingType(entityType).ToList(); } if (possibleFunctions.Count <= 0) { segment = null; return false; } segment = new OperationSegment(possibleFunctions, null /*entitySet*/); return true; }
private bool TryCreateSegmentForOperation(ODataPathSegment previousSegment, string identifier, string parenthesisExpression) { // Parse Arguments syntactically var bindingType = previousSegment == null ? null : previousSegment.EdmType; ICollection<OperationSegmentParameter> resolvedParameters; IEdmOperation singleOperation; if (!TryBindingParametersAndMatchingOperation(identifier, parenthesisExpression, bindingType, this.configuration, out resolvedParameters, out singleOperation)) { return false; } if (!UriEdmHelpers.IsBindingTypeValid(bindingType)) { throw ExceptionUtil.CreateBadRequestError(ODataErrorStrings.RequestUriProcessor_OperationSegmentBoundToANonEntityType); } if (previousSegment != null && bindingType == null) { throw new ODataException(ODataErrorStrings.FunctionCallBinder_CallingFunctionOnOpenProperty(identifier)); } IEdmTypeReference returnType = singleOperation.ReturnType; IEdmEntitySetBase targetset = null; if (returnType != null) { IEdmNavigationSource source = previousSegment == null ? null : previousSegment.TargetEdmNavigationSource; targetset = singleOperation.GetTargetEntitySet(source, this.configuration.Model); } // If previous segment is cross-referenced then we explicitly dissallow the service action call if (previousSegment is BatchReferenceSegment) { throw ExceptionUtil.CreateBadRequestError(ODataErrorStrings.RequestUriProcessor_BatchedActionOnEntityCreatedInSameChangeset(identifier)); } // TODO: change constructor to take single import ODataPathSegment segment = new OperationSegment(new[] { singleOperation }, resolvedParameters, targetset) { Identifier = identifier }; DetermineEntitySetForSegment(identifier, returnType, segment, targetset, singleOperation); this.parsedSegments.Add(segment); this.TryBindKeySegmentIfNoResolvedParametersAndParathesisValueExsts(parenthesisExpression, returnType, resolvedParameters, segment); return true; }