Пример #1
0
 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);
        }
Пример #3
0
        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);
        }
Пример #4
0
        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);
        }
Пример #5
0
        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);
        }
Пример #7
0
        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());
            }
        }
Пример #8
0
        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));
        }
Пример #9
0
        /// <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);
            }
        }
Пример #11
0
        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));
        }
Пример #12
0
        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);
                }
            }
        }
Пример #13
0
 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();
        }
Пример #15
0
        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));
        }
Пример #16
0
        /// <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;
        }
Пример #17
0
        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)));
            }
        }
Пример #18
0
        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));
        }
Пример #19
0
        /// <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);
            }
        }
Пример #20
0
        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);
        }
Пример #21
0
        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);
        }
Пример #23
0
        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);
        }
Пример #24
0
        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);
        }
Пример #25
0
        private static IEdmFunction GetFunction(OperationSegment segment)
        {
            if (segment != null)
            {
                IEdmFunction function = segment.Operations.First() as IEdmFunction;
                return(function);
            }

            return(null);
        }
Пример #26
0
        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'.");
        }
Пример #29
0
        /// <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);
        }
Пример #30
0
        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);
        }
Пример #31
0
        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);
        }
Пример #32
0
        /// <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.");
        }
Пример #33
0
 /// <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);
        }
Пример #35
0
        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;
        }
Пример #37
0
        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;
        }