public void CanManuallyConfigureFunctionLinkFactory() { // Arrange string uriTemplate = "http://server/service/Customers({0})/Reward"; Uri expectedUri = new Uri(string.Format(uriTemplate, 1)); ODataModelBuilder builder = new ODataModelBuilder(); EntityTypeConfiguration <Customer> customer = builder.EntitySet <Customer>("Customers").EntityType; customer.HasKey(c => c.CustomerId); customer.Property(c => c.Name); // Act FunctionConfiguration reward = customer.Function("Reward"); reward.HasFunctionLink(ctx => new Uri(string.Format(uriTemplate, ctx.GetPropertyValue("CustomerId"))), followsConventions: false); reward.Returns <bool>(); IEdmModel model = builder.GetEdmModel(); IEdmEntityType customerType = model.SchemaElements.OfType <IEdmEntityType>().SingleOrDefault(); ODataSerializerContext serializerContext = new ODataSerializerContext { Model = model }; ResourceContext context = new ResourceContext(serializerContext, customerType.AsReference(), new Customer { CustomerId = 1 }); IEdmFunction rewardFunction = Assert.Single(model.SchemaElements.OfType <IEdmFunction>()); // Guard OperationLinkBuilder functionLinkBuilder = model.GetAnnotationValue <OperationLinkBuilder>(rewardFunction); //Assert Assert.Equal(expectedUri, reward.GetFunctionLink()(context)); Assert.NotNull(functionLinkBuilder); Assert.Equal(expectedUri, functionLinkBuilder.BuildLink(context)); }
public void CanCreateEdmModel_WithNonBindableFunction() { // Arrange ODataModelBuilder builder = ODataModelBuilderMocks.GetModelBuilderMock <ODataModelBuilder>(); // Act FunctionConfiguration functionConfiguration = builder.Function("FunctionName"); functionConfiguration.ReturnsFromEntitySet <Customer>("Customers"); IEdmModel model = builder.GetEdmModel(); // Assert IEdmEntityContainer container = model.EntityContainer; Assert.NotNull(container); Assert.Single(container.Elements.OfType <IEdmFunctionImport>()); Assert.Single(container.Elements.OfType <IEdmEntitySet>()); IEdmFunctionImport functionImport = Assert.Single(container.Elements.OfType <IEdmFunctionImport>()); IEdmFunction function = functionImport.Function; Assert.False(function.IsComposable); Assert.False(function.IsBound); Assert.Equal("FunctionName", function.Name); Assert.NotNull(function.ReturnType); Assert.NotNull(functionImport.EntitySet); Assert.Equal("Customers", (functionImport.EntitySet as IEdmPathExpression).Path); Assert.Empty(function.Parameters); }
public void WhenFeedActionLinksNotManuallyConfigured_ConventionBasedBuilderUsesConventions() { // Arrange Uri expectedUri = new Uri("http://server/Movies/Default.Watch(param=@param)"); ODataModelBuilder builder = ODataConventionModelBuilderFactory.Create(); EntityTypeConfiguration <Movie> movie = builder.EntitySet <Movie>("Movies").EntityType; FunctionConfiguration watch = movie.Collection.Function("Watch").Returns <int>(); // function bound to collection watch.Parameter <string>("param"); IEdmModel model = builder.GetEdmModel(); var configuration = RoutingConfigurationFactory.Create(); string routeName = "Route"; configuration.MapODataServiceRoute(routeName, null, model); var request = RequestFactory.Create(HttpMethod.Get, "http://server/Movies", configuration, routeName); // Act IEdmEntityContainer container = model.SchemaElements.OfType <IEdmEntityContainer>().SingleOrDefault(); IEdmFunction watchFunction = Assert.Single(model.SchemaElements.OfType <IEdmFunction>()); // Guard IEdmEntitySet entitySet = container.EntitySets().SingleOrDefault(); ODataSerializerContextFactory.Create(model, entitySet, request); ResourceSetContext context = ResourceSetContextFactory.Create(entitySet, request); OperationLinkBuilder functionLinkBuilder = model.GetAnnotationValue <OperationLinkBuilder>(watchFunction); //Assert Assert.Equal(expectedUri, watch.GetFeedFunctionLink()(context)); Assert.NotNull(functionLinkBuilder); Assert.Equal(expectedUri, functionLinkBuilder.BuildLink(context)); }
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); } } }
private IEdmFunction GetFunction(string functionName) { IEdmFunction function = null; var functionImport = _model.SchemaElements .Where(x => x.SchemaElementKind == EdmSchemaElementKind.EntityContainer) .SelectMany(x => (x as IEdmEntityContainer).Elements .Where(y => y.ContainerElementKind == EdmContainerElementKind.FunctionImport)) .BestMatch(x => x.Name, functionName, NameMatchResolver) as IEdmFunctionImport; if (functionImport != null) { function = functionImport.Function; } if (function == null) { function = _model.SchemaElements .BestMatch(x => x.SchemaElementKind == EdmSchemaElementKind.Function, x => x.Name, functionName, NameMatchResolver) as IEdmFunction; } if (function == null) { throw new UnresolvableObjectException(functionName, $"Function [{functionName}] not found"); } return(function); }
/// <summary> /// Try to bind the idenfier as operation import (function import or action import) segment, /// Append it into path. /// </summary> private static bool TryBindOperationImport(string identifier, string parenthesisExpressions, IEdmModel model, IList <PathSegment> path, PathParserSettings settings) { // split the parameter key/value pair parenthesisExpressions.ExtractKeyValuePairs(out IDictionary <string, string> parameters, out string remaining); IList <string> parameterNames = parameters == null ? null : parameters.Keys.ToList(); IEdmOperationImport operationImport = OperationHelper.ResolveOperationImports(identifier, parameterNames, model, settings.EnableCaseInsensitive); if (operationImport != null) { operationImport.TryGetStaticEntitySet(model, out IEdmEntitySetBase entitySetBase); path.Add(new OperationImportSegment(operationImport, entitySetBase)); if (remaining != null && operationImport.IsFunctionImport()) { IEdmFunction function = (IEdmFunction)operationImport.Operation; if (function.IsComposable) { if (TryBindKeySegment(parenthesisExpressions, path)) { return(true); } } } return(true); } return(false); }
public void BuildFilter_AliasInFunction_PropertyAsValue_TypeMismatch() { Uri fullUri = new Uri("http://gobbledygook/People?$filter=Fully.Qualified.Namespace.HasDog(inOffice%3D%40p1%2Cname%3D%40p1)&@p2=Name&@p1=%40p2"); ODataUriParser odataUriParser = new ODataUriParser(HardCodedTestModel.TestModel, serviceRoot, fullUri); SetODataUriParserSettingsTo(this.settings, odataUriParser.Settings); odataUriParser.UrlKeyDelimiter = ODataUrlKeyDelimiter.Parentheses; ODataUri odataUri = odataUriParser.ParseUri(); IDictionary <string, SingleValueNode> aliasNodes = odataUri.ParameterAliasNodes; IEdmFunction function = HardCodedTestModel.GetHasDogOverloadForPeopleWithThreeParameters() as IEdmFunction; Assert.NotNull(function); var functionCallNode = odataUri.Filter.Expression.ShouldBeSingleValueFunctionCallQueryNode(function); Assert.IsType <NamedFunctionParameterNode>(functionCallNode.Parameters.Last()).Value.ShouldBeParameterAliasNode("@p1", EdmCoreModel.Instance.GetString(true)); aliasNodes["@p1"].ShouldBeParameterAliasNode("@p2", EdmCoreModel.Instance.GetString(true)); aliasNodes["@p2"].ShouldBeSingleValuePropertyAccessQueryNode(HardCodedTestModel.GetPeopleSet().EntityType().FindProperty("Name")); Uri actualUri = odataUri.BuildUri(ODataUrlKeyDelimiter.Parentheses); Assert.Equal(fullUri, actualUri); actualUri = odataUri.BuildUri(ODataUrlKeyDelimiter.Slash); Assert.Equal(fullUri, actualUri); }
/// <summary> /// Initializes a new instance of the <see cref="FunctionSegmentTemplate" /> class. /// </summary> /// <param name="parameters">The function parameter template mappings.The key string is case-sensitive, the value string should wrapper with { and }.</param> /// <param name="function">The Edm function, it should be bound function.</param> /// <param name="navigationSource">The Edm navigation source of this function return. It could be null.</param> public FunctionSegmentTemplate(IDictionary <string, string> parameters, IEdmFunction function, IEdmNavigationSource navigationSource) { if (parameters == null) { throw Error.ArgumentNull(nameof(parameters)); } Function = function ?? throw Error.ArgumentNull(nameof(function)); NavigationSource = navigationSource; // Only accept the bound function if (!function.IsBound) { throw new ODataException(Error.Format(SRResources.FunctionIsNotBound, function.Name)); } // Parameters should include all required parameter, but maybe include the optional parameter. ParameterMappings = function.VerifyAndBuildParameterMappings(parameters); // 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; }
public void CanCreateEdmModel_WithBindableFunction() { // Arrange ODataModelBuilder builder = new ODataModelBuilder(); EntityTypeConfiguration <Customer> customer = builder.EntityType <Customer>(); customer.HasKey(c => c.CustomerId); customer.Property(c => c.Name); // Act FunctionConfiguration sendEmail = customer.Function("FunctionName"); sendEmail.Returns <bool>(); IEdmModel model = builder.GetEdmModel(); // Assert Assert.Single(model.SchemaElements.OfType <IEdmFunction>()); IEdmFunction function = Assert.Single(model.SchemaElements.OfType <IEdmFunction>()); Assert.False(function.IsComposable); Assert.True(function.IsBound); Assert.Equal("FunctionName", function.Name); Assert.NotNull(function.ReturnType); Assert.Single(function.Parameters); Assert.Equal(BindingParameterConfiguration.DefaultBindingParameterName, function.Parameters.Single().Name); Assert.Equal(typeof(Customer).FullName, function.Parameters.Single().Type.FullName()); }
/// <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); } }
/// <summary> /// Initializes a new instance of the <see cref="FunctionSegmentTemplate" /> class. /// </summary> /// <param name="function">The Edm function, it should be bound function.</param> /// <param name="navigationSource">The Edm navigation source of this function return. It could be null.</param> /// <param name="requiredParameters">The required parameters of this function.</param> public FunctionSegmentTemplate(IEdmFunction function, IEdmNavigationSource navigationSource, ISet <string> requiredParameters) { Function = function ?? throw Error.ArgumentNull(nameof(function)); NavigationSource = navigationSource; RequiredParameters = requiredParameters ?? throw Error.ArgumentNull(nameof(requiredParameters)); // Only accept the bound function if (!function.IsBound) { throw new ODataException(string.Format(CultureInfo.CurrentCulture, SRResources.FunctionIsNotBound, function.Name)); } // make sure the input parameter is subset of the function paremeters. ISet <string> functionParameters = function.GetFunctionParamters(); if (!requiredParameters.IsSubsetOf(functionParameters)) { string required = string.Join(",", requiredParameters); string actual = string.Join(",", functionParameters); throw new ODataException(Error.Format(SRResources.RequiredParametersNotSubsetOfFunctionParameters, required, actual)); } // Join the parameters as p1={p1} string parameters = "(" + string.Join(",", requiredParameters.Select(a => $"{a}={{{a}}}")) + ")"; UnqualifiedIdentifier = function.Name + parameters; Literal = function.FullName() + parameters; // Function will always have the return type IsSingle = function.ReturnType.TypeKind() != EdmTypeKind.Collection; }
private string FunctionName(IEdmFunction function, OpenApiConvertSettings settings) { StringBuilder functionName = new StringBuilder(); if (settings.EnableUnqualifiedCall) { functionName.Append(function.Name); } else { functionName.Append(function.FullName()); } functionName.Append("("); // Structured or collection-valued parameters are represented as a parameter alias in the path template // and the parameters array contains a Parameter Object for the parameter alias as a query option of type string. int skip = function.IsBound ? 1 : 0; functionName.Append(String.Join(",", function.Parameters.Skip(skip).Select(p => { if (p.Type.IsStructured() || p.Type.IsCollection()) { return(p.Name + "=@" + p.Name); } else { return(p.Name + "={" + p.Name + "}"); } }))); functionName.Append(")"); return(functionName.ToString()); }
/// <summary> /// Initializes a new <see cref="IEdmOperationImport"/> instance. /// </summary> /// <param name="name">name of the service operation.</param> /// <param name="function">Function imported in.</param> /// <param name="resultSet">EntitySet of the result expected from this operation.</param> public EdmFunctionImport AddFunctionImport(string name, IEdmFunction function, IEdmEntitySet resultSet, bool includeInServiceDocument) { var functionImport = new EdmFunctionImport(this, name, function, new EdmEntitySetReferenceExpression(resultSet), includeInServiceDocument); this.AddOperationImport(name, functionImport); return(functionImport); }
/// <summary> /// Creates and adds a function import to this entity container. /// </summary> /// <param name="name">Name of the function import.</param> /// <param name="function">The function of the specified function import.</param> /// <param name="entitySet">An entity set containing entities returned by this function import. /// The two expression kinds supported are <see cref="IEdmEntitySetReferenceExpression"/> and <see cref="IEdmPathExpression"/>.</param> /// <param name="includeInServiceDocument">A value indicating whether this function import will be in the service document.</param> /// <returns>Created operation import.</returns> public virtual EdmOperationImport AddFunctionImport(string name, IEdmFunction function, IEdmExpression entitySet, bool includeInServiceDocument) { EdmOperationImport functionImport = new EdmFunctionImport(this, name, function, entitySet, includeInServiceDocument); this.AddElement(functionImport); return(functionImport); }
/// <inheritdoc/> protected override void SetParameters(OpenApiOperation operation) { base.SetParameters(operation); if (EdmOperation.IsFunction()) { IEdmFunction function = (IEdmFunction)EdmOperation; if (OperationSegment.ParameterMappings != null) { IList <OpenApiParameter> parameters = Context.CreateParameters(function, OperationSegment.ParameterMappings); foreach (var parameter in parameters) { AppendParameter(operation, parameter); } } else { IDictionary <string, string> mappings = ParameterMappings[OperationSegment]; IList <OpenApiParameter> parameters = Context.CreateParameters(function, mappings); if (operation.Parameters == null) { operation.Parameters = parameters; } else { foreach (var parameter in parameters) { AppendParameter(operation, parameter); } } } } }
private bool IsMatchingFunction(IEdmFunction function) { IEnumerable <EdmError> edmErrors = null; bool flag; if (function.Parameters.Count <IEdmFunctionParameter>() == this.Arguments.Count <IEdmExpression>()) { IEnumerator <IEdmExpression> enumerator = this.Arguments.GetEnumerator(); IEnumerator <IEdmFunctionParameter> enumerator1 = function.Parameters.GetEnumerator(); using (enumerator1) { while (enumerator1.MoveNext()) { IEdmFunctionParameter current = enumerator1.Current; enumerator.MoveNext(); if (enumerator.Current.TryAssertType(current.Type, out edmErrors)) { continue; } flag = false; return(flag); } return(true); } return(flag); } else { return(false); } }
private string FunctionImportName(IEdmFunctionImport functionImport, OpenApiConvertSettings settings) { StringBuilder functionName = new StringBuilder(functionImport.Name); functionName.Append("("); // Structured or collection-valued parameters are represented as a parameter alias in the path template // and the parameters array contains a Parameter Object for the parameter alias as a query option of type string. IEdmFunction function = functionImport.Function; functionName.Append(String.Join(",", function.Parameters.Select(p => { if (p.Type.IsStructured() || p.Type.IsCollection()) { return(p.Name + "=@" + p.Name); } else { return(p.Name + "={" + p.Name + "}"); } }))); functionName.Append(")"); return(functionName.ToString()); }
/// <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); } }
/// <summary> /// Initializes a new instance of the <see cref="FunctionSegmentTemplate" /> class. /// </summary> /// <param name="parameters">The function parameter template mappings.The key string is case-sensitive, the value string should wrapper with { and }.</param> /// <param name="function">The Edm function, it should be bound function.</param> /// <param name="navigationSource">The Edm navigation source of this function return. It could be null.</param> public FunctionSegmentTemplate(IDictionary <string, string> parameters, IEdmFunction function, IEdmNavigationSource navigationSource) { if (parameters == null) { throw Error.ArgumentNull(nameof(parameters)); } Function = function ?? throw Error.ArgumentNull(nameof(function)); NavigationSource = navigationSource; // Only accept the bound function if (!function.IsBound) { throw new ODataException(Error.Format(SRResources.FunctionIsNotBound, function.Name)); } // Parameters should include all required parameter, but maybe include the optional parameter. ParameterMappings = function.VerifyAndBuildParameterMappings(parameters); 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; }
/// <summary> /// Determines whether the specified function is UrlEscape function or not. /// </summary> /// <param name="model">The Edm model.</param> /// <param name="function">The specified function</param> /// <returns><c>true</c> if the specified operation is UrlEscape function; otherwise, <c>false</c>.</returns> public static bool IsUrlEscapeFunction(this IEdmModel model, IEdmFunction function) { Utils.CheckArgumentNull(model, nameof(model)); Utils.CheckArgumentNull(function, nameof(function)); IEdmVocabularyAnnotation annotation = model.FindVocabularyAnnotations <IEdmVocabularyAnnotation>(function, CommunityVocabularyModel.UrlEscapeFunctionTerm).FirstOrDefault(); if (annotation != null) { if (annotation.Value == null) { // If the annotation is applied but a value is not specified then the value is assumed to be true. return(true); } IEdmBooleanConstantExpression tagConstant = annotation.Value as IEdmBooleanConstantExpression; if (tagConstant != null) { return(tagConstant.Value); } } return(false); }
public void CreateOperationForEdmFunctionReturnsCorrectOperation() { // Arrange IEdmModel model = EdmModelHelper.TripServiceModel; ODataContext context = new ODataContext(model); IEdmEntitySet people = model.EntityContainer.FindEntitySet("People"); Assert.NotNull(people); IEdmFunction function = model.SchemaElements.OfType <IEdmFunction>().First(f => f.Name == "GetFavoriteAirline"); Assert.NotNull(function); ODataPath path = new ODataPath(new ODataNavigationSourceSegment(people), new ODataKeySegment(people.EntityType()), new ODataOperationSegment(function)); // Act var operation = _operationHandler.CreateOperation(context, path); // Assert Assert.NotNull(operation); Assert.Equal("Invoke function GetFavoriteAirline", operation.Summary); Assert.NotNull(operation.Tags); var tag = Assert.Single(operation.Tags); Assert.Equal("People.Functions", tag.Name); Assert.NotNull(operation.Parameters); Assert.Equal(1, operation.Parameters.Count); Assert.Equal(new string[] { "UserName" }, operation.Parameters.Select(p => p.Name)); Assert.Null(operation.RequestBody); Assert.Equal(2, operation.Responses.Count); Assert.Equal(new string[] { "200", "default" }, operation.Responses.Select(e => e.Key)); }
/// <summary> /// Creates and adds a function import to this entity container. /// </summary> /// <param name="name">Name of the function import.</param> /// <param name="function">The function of the specified function import.</param> /// <returns>Created function import.</returns> public virtual EdmFunctionImport AddFunctionImport(string name, IEdmFunction function) { EdmFunctionImport functionImport = new EdmFunctionImport(this, name, function); this.AddElement(functionImport); return(functionImport); }
protected override void ProcessFunction(IEdmFunction element) { Action <IEdmFunction> elementHeaderWriter = null; if (element.ReturnType != null) { bool inlineReturnType = IsInlineType(element.ReturnType); this.BeginElement <IEdmFunction>(element, f => this.schemaWriter.WriteFunctionElementHeader(f, inlineReturnType), new Action <IEdmFunction>[] { f => this.ProcessFacets(f.ReturnType, inlineReturnType) }); if (!inlineReturnType) { this.schemaWriter.WriteReturnTypeElementHeader(); base.VisitTypeReference(element.ReturnType); this.schemaWriter.WriteEndElement(); } } else { if (elementHeaderWriter == null) { elementHeaderWriter = t => this.schemaWriter.WriteFunctionElementHeader(t, false); } this.BeginElement <IEdmFunction>(element, elementHeaderWriter, new Action <IEdmFunction> [0]); } if (element.DefiningExpression != null) { this.schemaWriter.WriteDefiningExpressionElement(element.DefiningExpression); } base.VisitFunctionParameters(element.Parameters); this.EndElement(element); }
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))); } }
/// <summary> /// /// </summary> /// <param name="function">The type containes the key.</param> /// <param name="unqualifiedFunctionCall">Unqualified function call boolean value.</param> public FunctionSegmentTemplate(IEdmFunction function, bool unqualifiedFunctionCall) { Function = function ?? throw new ArgumentNullException(nameof(function)); if (!function.IsBound) { // TODO: shall we need this check? throw new InvalidOperationException($"The input function {function.Name} is not a bound function."); } int skip = function.IsBound ? 1 : 0; IDictionary <string, string> parametersMappings = new Dictionary <string, string>(); foreach (var parameter in function.Parameters.Skip(skip)) { parametersMappings[parameter.Name] = $"{{{parameter.Name}}}"; } if (unqualifiedFunctionCall) { Template = function.Name + "(" + string.Join(",", parametersMappings.Select(a => $"{a.Key}={a.Value}")) + ")"; } else { Template = function.FullName() + "(" + string.Join(",", parametersMappings.Select(a => $"{a.Key}={a.Value}")) + ")"; } }
public static BoundFunctionPathSegment TryResolveBound(IEnumerable <IEdmFunction> functions, IEdmModel model, string nextSegment) { Dictionary <string, string> parameters = GetParameters(nextSegment); IEnumerable <string> parameterNames; if (parameters == null) { parameterNames = null; } else if (parameters.Keys.Contains(String.Empty)) { // One of the function parameters has no name. return(null); } else { parameterNames = parameters.Keys; } IEdmFunction function = FindBestBoundFunction(functions, parameterNames); if (function != null) { if (GetNonBindingParameters(function).Any()) { return(new BoundFunctionPathSegment(function, model, parameters)); } else { return(new BoundFunctionPathSegment(function, model, parameterValues: null)); } } return(null); }
public static bool IsBoundTo(IEdmFunction function, IEdmType type) { Contract.Assert(function != null); Contract.Assert(type != null); // The binding parameter is the first parameter by convention IEdmOperationParameter bindingParameter = function.Parameters.FirstOrDefault(); if (bindingParameter == null) { return(false); } IEdmType fromType; if (bindingParameter.Type.Definition.TypeKind == EdmTypeKind.Collection) { fromType = ((IEdmCollectionType)bindingParameter.Type.Definition).ElementType.Definition; } else { fromType = bindingParameter.Type.Definition; } return(fromType == type); }
protected override void ProcessFunction(IEdmFunction element) { if (element.ReturnType != null) { bool inlineReturnType = IsInlineType(element.ReturnType); this.BeginElement(element, (IEdmFunction f) => { this.schemaWriter.WriteFunctionElementHeader(f, inlineReturnType); }, f => { this.ProcessFacets(f.ReturnType, inlineReturnType); }); if (!inlineReturnType) { this.schemaWriter.WriteReturnTypeElementHeader(); this.VisitTypeReference(element.ReturnType); this.schemaWriter.WriteEndElement(); } } else { this.BeginElement(element, (IEdmFunction t) => { this.schemaWriter.WriteFunctionElementHeader(t, false /*Inline ReturnType*/); }); } if (element.DefiningExpression != null) { this.schemaWriter.WriteDefiningExpressionElement(element.DefiningExpression); } this.VisitFunctionParameters(element.Parameters); this.EndElement(element); }
/// <summary> /// Verify and build the function parameters /// </summary> /// <param name="function">The Edm function.</param> /// <param name="parameters">The input parameter template mapping.</param> /// <returns>The build function parameter mapping.</returns> public static IDictionary <string, string> VerifyAndBuildParameterMappings(this IEdmFunction function, IDictionary <string, string> parameters) { if (function == null) { throw Error.ArgumentNull(nameof(function)); } if (parameters == null) { throw Error.ArgumentNull(nameof(parameters)); } Dictionary <string, string> parameterMappings = new Dictionary <string, string>(); int skip = function.IsBound ? 1 : 0; ISet <string> funcParameters = new HashSet <string>(); foreach (var parameter in function.Parameters.Skip(skip)) { funcParameters.Add(parameter.Name); IEdmOptionalParameter optionalParameter = parameter as IEdmOptionalParameter; if (optionalParameter != null) { // skip verification for optional parameter continue; } // for required parameter, it should be in the parameter template mapping. if (!parameters.ContainsKey(parameter.Name)) { throw new ODataException(Error.Format(SRResources.MissingRequiredParameterInOperation, parameter.Name, function.FullName())); } } foreach (var parameter in parameters) { if (!funcParameters.Contains(parameter.Key)) { throw new ODataException(Error.Format(SRResources.CannotFindParameterInOperation, parameter.Key, function.FullName())); } string templateName = parameter.Value; if (templateName == null || !templateName.IsValidTemplateLiteral()) { throw new ODataException(Error.Format(SRResources.ParameterTemplateMustBeInCurlyBraces, parameter.Value, function.FullName())); } templateName = templateName.Substring(1, templateName.Length - 2).Trim(); if (string.IsNullOrEmpty(templateName)) { throw new ODataException(Error.Format(SRResources.EmptyParameterAlias, parameter.Key, function.FullName())); } parameterMappings[parameter.Key] = templateName; } return(parameterMappings); }
/// <summary> /// Ases the edm function. /// </summary> /// <param name="function">The function.</param> /// <returns></returns> public static EdmFunction AsEdmFunction(this IEdmFunction function) { var edmAction = function as EdmFunction; ExceptionUtilities.CheckObjectNotNull(edmAction, "function"); return(edmAction); }
/// <summary> /// Initializes a new instance of the <see cref="EdmFunctionImport"/> class. /// </summary> /// <param name="container">The container.</param> /// <param name="name">The name.</param> /// <param name="function">The function.</param> /// <param name="entitySetExpression">The entity set expression.</param> /// <param name="includeInServiceDocument">The value indicates if the function is to be include in the service document or not.</param> public EdmFunctionImport(IEdmEntityContainer container, string name, IEdmFunction function, IEdmExpression entitySetExpression, bool includeInServiceDocument) : base(container, function, name, entitySetExpression) { EdmUtil.CheckArgumentNull(function, "function"); this.Function = function; this.IncludeInServiceDocument = includeInServiceDocument; }
public static void SetFunctionLinkBuilder(this IEdmModel model, IEdmFunction function, FunctionLinkBuilder functionLinkBuilder) { if (model == null) { throw Error.ArgumentNull("model"); } model.SetAnnotationValue(function, functionLinkBuilder); }
/// <summary> /// Initializes a new instance of the <see cref="BoundFunctionPathSegment" /> class. /// </summary> /// <param name="function">The function being invoked.</param> /// <param name="model">The edm model containing the function.</param> /// <param name="parameterValues">The raw parameter values indexed by the parameter names.</param> public BoundFunctionPathSegment(IEdmFunction function, IEdmModel model, IDictionary<string, string> parameterValues) { if (function == null) { throw Error.ArgumentNull("function"); } Function = function; FunctionName = Function.FullName(); _edmModel = model; Values = parameterValues ?? new Dictionary<string, string>(); }
public ODataSwaggerUtilitiesTest() { CustomersModelWithInheritance model = new CustomersModelWithInheritance(); _customer = model.Customer; _customers = model.Customers; IEdmAction action = new EdmAction("NS", "GetCustomers", null, false, null); _getCustomers = new EdmActionImport(model.Container, "GetCustomers", action); _isAnyUpgraded = model.Model.SchemaElements.OfType<IEdmFunction>().FirstOrDefault(e => e.Name == "IsAnyUpgraded"); _isCustomerUpgradedWithParam = model.Model.SchemaElements.OfType<IEdmFunction>().FirstOrDefault(e => e.Name == "IsUpgradedWithParam"); }
internal static bool FunctionOrNameExistsInReferencedModel(this IEdmModel model, IEdmFunction function, string functionFullName, bool checkEntityContainer) { bool flag; Func<IEdmFunction, bool> func = null; IEnumerator<IEdmModel> enumerator = model.ReferencedModels.GetEnumerator(); using (enumerator) { while (enumerator.MoveNext()) { IEdmModel current = enumerator.Current; if (current.FindDeclaredType(functionFullName) != null || current.FindDeclaredValueTerm(functionFullName) != null || checkEntityContainer && current.FindDeclaredEntityContainer(functionFullName) != null) { flag = true; return flag; } else { IEnumerable<IEdmFunction> edmFunctions = current.FindDeclaredFunctions(functionFullName); IEnumerable<IEdmFunction> edmFunctions1 = edmFunctions; if (edmFunctions == null) { edmFunctions1 = Enumerable.Empty<IEdmFunction>(); } IEnumerable<IEdmFunction> edmFunctions2 = edmFunctions1; IEnumerable<IEdmFunction> edmFunctions3 = edmFunctions2; if (func == null) { func = (IEdmFunction existingFunction) => function.IsFunctionSignatureEquivalentTo(existingFunction); } if (!edmFunctions3.Any<IEdmFunction>(func)) { continue; } flag = true; return flag; } } return false; } return flag; }
public static void AddFunctionParameters(IEdmFunction function, string paramName, object paramValue, IDictionary<string, object> routeData, IDictionary<string, object> values, IDictionary<string, string> paramMapping) { Contract.Assert(function != null); // using the following codes to support [FromODataUriAttribute] IEdmOperationParameter edmParam = function.FindParameter(paramName); Contract.Assert(edmParam != null); ODataParameterValue parameterValue = new ODataParameterValue(paramValue, edmParam.Type); string name = paramName; if (paramMapping != null) { Contract.Assert(paramMapping.ContainsKey(paramName)); name = paramMapping[paramName]; } string prefixName = ODataParameterValue.ParameterValuePrefix + name; values[prefixName] = parameterValue; // using the following codes to support [FromUriAttribute] if (!routeData.ContainsKey(name)) { routeData.Add(name, paramValue); } ODataNullValue nullValue = paramValue as ODataNullValue; if (nullValue != null) { routeData[name] = null; } ODataEnumValue enumValue = paramValue as ODataEnumValue; if (enumValue != null) { // Remove the type name of the ODataEnumValue and keep the value. routeData[name] = enumValue.Value; } }
public static bool IsBoundTo(IEdmFunction function, IEdmType type) { Contract.Assert(function != null); Contract.Assert(type != null); // The binding parameter is the first parameter by convention IEdmOperationParameter bindingParameter = function.Parameters.FirstOrDefault(); if (bindingParameter == null) { return false; } IEdmType fromType; if (bindingParameter.Type.Definition.TypeKind == EdmTypeKind.Collection) { fromType = ((IEdmCollectionType)bindingParameter.Type.Definition).ElementType.Definition; } else { fromType = bindingParameter.Type.Definition; } return fromType == type; }
IEdmObject InvokeFuncComplex(IEdmFunction func, JObject parameterValues, ODataQueryOptions queryOptions = null) { IEdmType edmType = func.ReturnType.Definition; IEdmType elementType = null; var rtv = new EdmComplexObject(edmType as IEdmComplexType); object obj; rtv.TryGetPropertyValue("$Results", out obj); EdmComplexObjectCollection collection = obj as EdmComplexObjectCollection; var colltype = (edmType as IEdmComplexType).FindProperty("$Results").Type.Definition; elementType = (colltype as IEdmCollectionType).ElementType.Definition; using (DbAccess db = new DbAccess(this.ConnectionString)) { var par = db.ExecuteReader(func.Name, (reader) => { EdmComplexObject entity = new EdmComplexObject(elementType as IEdmComplexType); for (int i = 0; i < reader.FieldCount; i++) { reader.SetEntityPropertyValue(i, entity); } collection.Add(entity); }, (pars) => { SetParameter(func, parameterValues, edmType, pars); var d1 = this.ParameterInfos[func.Name]; foreach (var p in (edmType as IEdmComplexType).Properties()) { if (p.Name == "$Results") continue; var pp = d1[p.Name]; pars.Add(new SqlParameter(p.Name, pp.SqlDbType, pp.Length) { Direction = ParameterDirection.Output }); } }); foreach (var outp in (edmType as IEdmComplexType).Properties()) { if (outp.Name == "$Results") continue; var v = par[outp.Name].Value; if (DBNull.Value != v) rtv.TrySetPropertyValue(outp.Name, v); } } return rtv; }
IEdmObject InvokeTVF(IEdmFunction func, JObject parameterValues, ODataQueryOptions queryOptions = null) { IEdmType edmType = func.ReturnType.Definition; IEdmType elementType = (edmType as IEdmCollectionType).ElementType.Definition; EdmComplexObjectCollection collection = new EdmComplexObjectCollection(new EdmCollectionTypeReference(edmType as IEdmCollectionType)); var target = BuildTVFTarget(func, parameterValues); var cmd = BuildSqlQueryCmd(queryOptions, target); using (DbAccess db = new DbAccess(this.ConnectionString)) { db.ExecuteReader(cmd, (reader) => { EdmComplexObject entity = new EdmComplexObject(elementType as IEdmComplexType); for (int i = 0; i < reader.FieldCount; i++) { reader.SetEntityPropertyValue(i, entity); } collection.Add(entity); }, null, CommandType.Text); } return collection; }
static void SetParameter(IEdmFunction func, JObject parameterValues, IEdmType edmType, SqlParameterCollection pars) { if (parameterValues == null) return; JToken token = null; Type colType = null; foreach (var p in func.Parameters) { if (parameterValues.TryGetValue(p.Name, out token)) { if (p.Type.Definition.TypeKind == EdmTypeKind.Complex) { DataTable dt = new DataTable(); var c = p.Type.AsComplex(); foreach (var item in c.StructuralProperties()) { dt.Columns.Add(item.Name, item.Type.PrimitiveKind().ToClrType()); } foreach (var item in token) { DataRow dr = dt.NewRow(); foreach (JProperty col in item) { if (!dt.Columns.Contains(col.Name)) continue; colType = dt.Columns[col.Name].DataType; if (colType == typeof(Boolean)) { dr.SetField(col.Name, col.Value.ToString() == "0" ? false : true); } else dr.SetField(col.Name, col.Value.ToString().ChangeType(colType)); } dt.Rows.Add(dr); } pars.AddWithValue(p.Name, dt); } else { if (string.IsNullOrEmpty(token.ToString())) pars.AddWithValue(p.Name, DBNull.Value); else pars.AddWithValue(p.Name, token.ToString().ChangeType(p.Type.PrimitiveKind())); } } } if (edmType.TypeKind == EdmTypeKind.Entity) { foreach (var outp in (edmType as EdmEntityType).Properties()) { if (outp.Name == "$Results") continue; if (pars.Contains(outp.Name)) { pars[outp.Name].Direction = ParameterDirection.Output; } else { pars.AddWithValue(outp.Name, DBNull.Value); } } } }
IEdmObject InvokeFuncCollection(IEdmFunction func, JObject parameterValues, ODataQueryOptions queryOptions = null) { IEdmType edmType = func.ReturnType.Definition; IEdmType elementType = (edmType as IEdmCollectionType).ElementType.Definition; EdmComplexObjectCollection collection = new EdmComplexObjectCollection(new EdmCollectionTypeReference(edmType as IEdmCollectionType)); using (DbAccess db = new DbAccess(this.ConnectionString)) { db.ExecuteReader(func.Name, (reader) => { EdmComplexObject entity = new EdmComplexObject(elementType as IEdmComplexType); for (int i = 0; i < reader.FieldCount; i++) { reader.SetEntityPropertyValue(i, entity); } collection.Add(entity); }, (pars) => { SetParameter(func, parameterValues, edmType, pars); }); } return collection; }
public virtual ODataFunction CreateODataFunction(IEdmFunction function, EntityInstanceContext entityInstanceContext) { if (function == null) { throw Error.ArgumentNull("function"); } if (entityInstanceContext == null) { throw Error.ArgumentNull("entityInstanceContext"); } IEdmModel model = entityInstanceContext.EdmModel; FunctionLinkBuilder builder = model.GetFunctionLinkBuilder(function); if (builder == null) { return null; } return CreateODataOperation(function, builder, entityInstanceContext) as ODataFunction; }
private bool IsMatchingFunction(IEdmFunction function) { IEnumerable<EdmError> edmErrors = null; bool flag; if (function.Parameters.Count<IEdmFunctionParameter>() == this.Arguments.Count<IEdmExpression>()) { IEnumerator<IEdmExpression> enumerator = this.Arguments.GetEnumerator(); IEnumerator<IEdmFunctionParameter> enumerator1 = function.Parameters.GetEnumerator(); using (enumerator1) { while (enumerator1.MoveNext()) { IEdmFunctionParameter current = enumerator1.Current; enumerator.MoveNext(); if (enumerator.Current.TryAssertType(current.Type, out edmErrors)) { continue; } flag = false; return flag; } return true; } return flag; } else { return false; } }
static string BuildTVFTarget(IEdmFunction func, JObject parameterValues) { string templete = "{0}({1})"; List<string> ps = new List<string>(); foreach (var p in func.Parameters) { ps.Add(parameterValues[p.Name].ToString()); } return string.Format(templete, func.Name, string.Join(",", ps)); }
/// <summary> /// Creates and adds a function import to this entity container. /// </summary> /// <param name="name">Name of the function import.</param> /// <param name="function">The function of the specified function import.</param> /// <param name="entitySet">An entity set containing entities returned by this function import. /// The two expression kinds supported are <see cref="IEdmEntitySetReferenceExpression"/> and <see cref="IEdmPathExpression"/>.</param> /// <param name="includeInServiceDocument">A value indicating whether this function import will be in the service document.</param> /// <returns>Created operation import.</returns> public virtual EdmOperationImport AddFunctionImport(string name, IEdmFunction function, IEdmExpression entitySet, bool includeInServiceDocument) { EdmOperationImport functionImport = new EdmFunctionImport(this, name, function, entitySet, includeInServiceDocument); this.AddElement(functionImport); return functionImport; }
/// <summary> /// Initializes a new instance of the <see cref="EdmFunctionImport"/> class. /// </summary> /// <param name="container">The container.</param> /// <param name="name">The name.</param> /// <param name="function">The function.</param> public EdmFunctionImport(IEdmEntityContainer container, string name, IEdmFunction function) : this(container, name, function, null, false) { }
public CsdlSemanticsFunctionImport(CsdlSemanticsEntityContainer container, CsdlFunctionImport functionImport, IEdmFunction backingfunction) : base(container, functionImport, backingfunction) { this.csdlSchema = container.Context; this.functionImport = functionImport; }
/// <summary> /// Initializes a new <see cref="IEdmOperationImport"/> instance. /// </summary> /// <param name="name">name of the service operation.</param> /// <param name="function">Function imported in.</param> /// <param name="resultSet">EntitySet of the result expected from this operation.</param> public EdmFunctionImport AddFunctionImport(string name, IEdmFunction function, IEdmEntitySet resultSet, bool includeInServiceDocument) { var functionImport = new EdmFunctionImport(this, name, function, new EdmEntitySetReferenceExpression(resultSet), includeInServiceDocument); this.AddOperationImport(name, functionImport); return functionImport; }
public EdmApplyExpression(IEdmFunction appliedFunction, IEdmExpression[] arguments) : this(appliedFunction, (IEnumerable<IEdmExpression>)arguments) { }
public IEnumerable<IEdmFunction> FindDeclaredFunctions(string qualifiedName) { object obj = null; if (!this.functionDictionary.TryGetValue(qualifiedName, out obj)) { return Enumerable.Empty<IEdmFunction>(); } else { List<IEdmFunction> edmFunctions = obj as List<IEdmFunction>; if (edmFunctions == null) { IEdmFunction[] edmFunctionArray = new IEdmFunction[1]; edmFunctionArray[0] = (IEdmFunction)obj; return edmFunctionArray; } else { return edmFunctions; } } }
private static IEnumerable<IEdmOperationParameter> GetNonBindingParameters(IEdmFunction function) { IEnumerable<IEdmOperationParameter> functionParameters = function.Parameters; if (function.IsBound) { // skip the binding parameter(first one by convention) for matching. functionParameters = functionParameters.Skip(1); } return functionParameters; }
public static FunctionLinkBuilder GetFunctionLinkBuilder(this IEdmModel model, IEdmFunction function) { if (model == null) { throw Error.ArgumentNull("model"); } if (function == null) { throw Error.ArgumentNull("function"); } FunctionLinkBuilder functionLinkBuilder = model.GetAnnotationValue<FunctionLinkBuilder>(function); if (functionLinkBuilder == null) { if (function.Parameters != null) { if (function.Parameters.First().Type.IsEntity()) { functionLinkBuilder = new FunctionLinkBuilder( (EntityInstanceContext entityInstanceContext) => entityInstanceContext.GenerateFunctionLink(function), followsConventions: true); } else if (function.Parameters.First().Type.IsCollection()) { functionLinkBuilder = new FunctionLinkBuilder( (FeedContext feedContext) => feedContext.GenerateFunctionLink(function), followsConventions: true); } } model.SetFunctionLinkBuilder(function, functionLinkBuilder); } return functionLinkBuilder; }
private static bool IsMatch(IEdmFunction function, HashSet<string> parameterNamesSet) { IEnumerable<IEdmOperationParameter> nonBindingParameters = GetNonBindingParameters(function); return parameterNamesSet.SetEquals(nonBindingParameters.Select(p => p.Name)); }
public EdmApplyExpression(IEdmFunction appliedFunction, IEnumerable<IEdmExpression> arguments) : this(new EdmFunctionReferenceExpression(EdmUtil.CheckArgumentNull<IEdmFunction>(appliedFunction, "appliedFunction")), arguments) { }
public int GetFuncResultCount(IEdmFunction func, JObject parameterValues, ODataQueryOptions queryOptions) { int count = 0; IEdmType edmType = func.ReturnType.Definition; if (this.PermissionCheck != null && !this.PermissionCheck(MethodType.Count, func.Name)) { throw new UnauthorizedAccessException(); } if (TVFList.Contains(func.Name)) { var target = BuildTVFTarget(func, parameterValues); var cmd = BuildSqlQueryCmd(queryOptions, target); using (DbAccess db = new DbAccess(this.ConnectionString)) { var r = db.ExecuteScalar(cmd, null, CommandType.Text); if (r != null) count = (int)r; } } return count; }
public IEdmObject InvokeFunction(IEdmFunction func, JObject parameterValues, ODataQueryOptions queryOptions = null) { if (this.PermissionCheck != null && !this.PermissionCheck(MethodType.Func, func.Name)) { throw new UnauthorizedAccessException(); } if (TVFList.Contains(func.Name)) return InvokeTVF(func, parameterValues, queryOptions); IEdmType edmType = func.ReturnType.Definition; if (edmType.TypeKind == EdmTypeKind.Collection) return InvokeFuncCollection(func, parameterValues, queryOptions); return InvokeFuncComplex(func, parameterValues, queryOptions); }
/// <summary> /// Creates and adds a function import to this entity container. /// </summary> /// <param name="name">Name of the function import.</param> /// <param name="function">The function of the specified function import.</param> /// <returns>Created function import.</returns> public virtual EdmFunctionImport AddFunctionImport(string name, IEdmFunction function) { EdmFunctionImport functionImport = new EdmFunctionImport(this, name, function); this.AddElement(functionImport); return functionImport; }
static string BuildTVFTarget(IEdmFunction func, JObject parameterValues) { string templete = "{0}({1})"; List<string> ps = new List<string>(); foreach (var p in func.Parameters) { if (p.Type.IsGuid() || p.Type.IsString() || p.Type.IsDateTimeOffset()) ps.Add(string.Format("'{0}'", parameterValues[p.Name].ToString())); else ps.Add(parameterValues[p.Name].ToString()); } return string.Format(templete, func.Name, string.Join(",", ps)); }
private bool IsMatchingFunction(IEdmFunction function) { if (function.Parameters.Count() != this.Arguments.Count()) { return false; } IEnumerator<IEdmExpression> parameterExpressionEnumerator = this.Arguments.GetEnumerator(); foreach (IEdmFunctionParameter parameter in function.Parameters) { parameterExpressionEnumerator.MoveNext(); IEnumerable<EdmError> recursiveErrors; if (!parameterExpressionEnumerator.Current.TryAssertType(parameter.Type, out recursiveErrors)) { return false; } } return true; }
public EdmFunctionReferenceExpression(IEdmFunction referencedFunction) { EdmUtil.CheckArgumentNull<IEdmFunction>(referencedFunction, "referencedFunction"); this.referencedFunction = referencedFunction; }