internal override IEdmTypeReference GetReturnType(IEdmOperationImport operationImport) { if (operationImport != null && operationImport.Operation.ReturnType != null) { return this.ResolveTypeReference(operationImport.Operation.ReturnType); } return null; }
private static IEnumerable<IEdmOperationParameter> GetNonBindingParameters(IEdmOperationImport operation) { IEnumerable<IEdmOperationParameter> functionParameters = operation.Operation.Parameters; if (operation.Operation.IsBound) { // skip the binding parameter(first one by convention) for matching. functionParameters = functionParameters.Skip(1); } return functionParameters; }
/// <summary> /// Gets the target entity set for the given operation import. /// </summary> /// <param name="operationImport">The operation import.</param> /// <param name="sourceEntitySet">The source entity set.</param> /// <param name="model">The model.</param> /// <returns>The target entity set of the operation import or null if it could not be determined.</returns> internal static IEdmEntitySetBase GetTargetEntitySet(this IEdmOperationImport operationImport, IEdmEntitySetBase sourceEntitySet, IEdmModel model) { IEdmEntitySetBase targetEntitySet; if (operationImport.TryGetStaticEntitySet(model, out targetEntitySet)) { return(targetEntitySet); } if (sourceEntitySet == null) { return(null); } if (operationImport.Operation.IsBound && operationImport.Operation.Parameters.Any()) { IEdmOperationParameter parameter; Dictionary <IEdmNavigationProperty, IEdmPathExpression> path; IEnumerable <EdmError> errors; if (operationImport.TryGetRelativeEntitySetPath(model, out parameter, out path, out errors)) { IEdmEntitySetBase currentEntitySet = sourceEntitySet; foreach (var navigation in path) { currentEntitySet = currentEntitySet.FindNavigationTarget(navigation.Key, navigation.Value) as IEdmEntitySetBase; if (currentEntitySet is IEdmUnknownEntitySet) { return(currentEntitySet); } } return(currentEntitySet); } else { if (errors.Any( e => e.ErrorCode == EdmErrorCode.InvalidPathFirstPathParameterNotMatchingFirstParameterName)) { throw ExceptionUtil.CreateSyntaxError(); } } } return(null); }
public void MetadataDocumentWithODataAnnotationsWriterTest() { IEdmModel model = Microsoft.Test.OData.Utils.Metadata.TestModels.BuildODataAnnotationTestModel(false); // NamedStream IEdmEntityType personType = model.FindType("TestModel.PersonType") as IEdmEntityType; this.Assert.IsNotNull(personType, "Expected to find the person type."); // MIME types IEdmProperty nameProperty = personType.DeclaredProperties.Where(p => p.Name == "Name").Single(); model.SetMimeType(nameProperty, "text/plain"); IEdmProperty addressProperty = personType.DeclaredProperties.Where(p => p.Name == "Address").Single(); IEdmComplexType addressType = addressProperty.Type.Definition as IEdmComplexType; this.Assert.IsNotNull(addressType, "Expected address to have a complex type."); IEdmProperty zipProperty = addressType.DeclaredProperties.Where(p => p.Name == "Zip").Single(); model.SetMimeType(zipProperty, "text/plain"); IEnumerable <IEdmOperationImport> functionGroup = model.EntityContainer.FindOperationImports("ServiceOperation1"); IEdmOperationImport functionImport = functionGroup.Single() as IEdmOperationImport; this.Assert.IsNotNull(functionImport, "Expected to find the function import."); model.SetMimeType(functionImport.Operation, "img/jpeg"); MetadataWriterTestDescriptor[] testDescriptors = new MetadataWriterTestDescriptor[] { new MetadataWriterTestDescriptor(this.Settings) { EdmVersion = EdmVersion.V40, Model = model, } }; this.CombinatorialEngineProvider.RunCombinations( testDescriptors, this.WriterTestConfigurationProvider.DefaultFormatConfigurationsWithIndent .Where(tc => tc.Synchronous && !tc.IsRequest), (testDescriptor, testConfiguration) => { testDescriptor.RunTest(testConfiguration, this.Logger); }); }
/// <summary> /// Load operation imports from model's metadata provider. /// </summary> /// <param name="qualifiedName">The name of the entity set to be loaded.</param> /// <returns>Operation imports that are loaded.</returns> internal List <IEdmOperationImport> LazyLoadServiceOperationImports(string qualifiedName) { List <IEdmOperationImport> operationImports = new List <IEdmOperationImport>(); OperationWrapper operationWrapper = this.model.MetadataProvider.TryResolveServiceOperation(qualifiedName); if (operationWrapper != null) { IEdmOperationImport foundOperationImport = this.model.EnsureDefaultEntityContainer().EnsureOperationImport(operationWrapper); if (foundOperationImport != null) { operationImports.Add(foundOperationImport); } } else { var operationWrapperQaulified = this.model.MetadataProvider.TryResolveServiceOperation(this.containerName + "." + qualifiedName); if (operationWrapperQaulified != null) { IEdmOperationImport foundOperationImport = this.model.EnsureDefaultEntityContainer().EnsureOperationImport(operationWrapperQaulified); if (foundOperationImport != null) { operationImports.Add(foundOperationImport); } } } // metadata interface in addition to the action provider interface. if (this.model.ActionProviderWrapper != null) { bool nameIsContainerQualified; var operationName = this.model.MetadataProvider.GetNameFromContainerQualifiedName(qualifiedName, out nameIsContainerQualified); var operation = this.model.ActionProviderWrapper.TryResolveServiceAction(operationName, MetadataProviderUtils.GetResourceType((IEdmType)null)); if (operation != null) { // Only top level actions will have an operation import. IEdmOperationImport foundOperationImport = this.model.EnsureDefaultEntityContainer().EnsureOperationImport(operation); if (foundOperationImport != null) { operationImports.Add(foundOperationImport); } } } return(operationImports); }
/// <summary> /// Returns the return type of the given operation import group. /// </summary> /// <param name="functionImportGroup">The operation import group to get the return type from.</param> /// <returns>The <see cref="IEdmType"/> representing the return type fo the <paramref name="functionImportGroup"/>.</returns> internal override IEdmTypeReference GetReturnType(IEnumerable <IEdmOperationImport> functionImportGroup) { Debug.Assert(functionImportGroup != null, "functionImportGroup != null"); IEdmOperationImport firstFunctionImport = functionImportGroup.FirstOrDefault(); Debug.Assert(firstFunctionImport != null, "firstFunctionImport != null"); Debug.Assert( functionImportGroup.All(f => { IEdmTypeReference returnType = this.GetReturnType(f); IEdmTypeReference actual = this.GetReturnType(firstFunctionImport); return(returnType == null && actual == null || returnType.IsEquivalentTo(actual)); }), "In a valid model, the return type of operation imports from the same operation import group should be the same."); return(this.GetReturnType(firstFunctionImport)); }
public void ParameterReaderAdditionalNullValueTest() { IEdmModel model = TestModels.BuildModelWithFunctionImport(); IEdmOperationImport functionImport_Complex = model.FindEntityContainer("TestContainer").FindOperationImports("FunctionImport_Complex").First(); IEdmOperationImport functionImport_PrimitiveCollection = model.FindEntityContainer("TestContainer").FindOperationImports("FunctionImport_PrimitiveCollection").First(); IEdmOperationImport functionImport_ComplexCollection = model.FindEntityContainer("TestContainer").FindOperationImports("FunctionImport_ComplexCollection").First(); var testConfigurations = this.ReaderTestConfigurationProvider.JsonLightFormatConfigurations.Where(c => c.IsRequest); this.CombinatorialEngineProvider.RunCombinations( testConfigurations, (testConfiguration) => { ODataParameterReader reader = this.CreateParameterReaderForRequestOrResponse(model, functionImport_PrimitiveCollection, testConfiguration, "{\"primitiveCollection\":null}"); reader.Read(); this.Assert.AreEqual("primitiveCollection", reader.Name, "Unexpected first parameter name."); this.Assert.IsNull(reader.Value, "Unexpected first parameter value."); this.Assert.AreEqual(ODataParameterReaderState.Value, reader.State, "Unexpected first parameter state."); reader = this.CreateParameterReaderForRequestOrResponse(model, functionImport_PrimitiveCollection, testConfiguration, "{\"primitiveCollection\":123}"); this.Assert.ExpectedException( () => reader.Read(), ODataExpectedExceptions.ODataException("ODataJsonLightParameterDeserializer_NullCollectionExpected", "PrimitiveValue", "123"), this.ExceptionVerifier); this.Assert.AreEqual(ODataParameterReaderState.Exception, reader.State, "Unexpected first parameter state."); reader = this.CreateParameterReaderForRequestOrResponse(model, functionImport_ComplexCollection, testConfiguration, "{\"complexCollection\":null}"); reader.Read(); this.Assert.AreEqual("complexCollection", reader.Name, "Unexpected first parameter name."); this.Assert.IsNull(reader.Value, "Unexpected first parameter value."); this.Assert.AreEqual(ODataParameterReaderState.Value, reader.State, "Unexpected first parameter state."); reader = this.CreateParameterReaderForRequestOrResponse(model, functionImport_ComplexCollection, testConfiguration, "{\"complexCollection\":123}"); this.Assert.ExpectedException( () => reader.Read(), ODataExpectedExceptions.ODataException("ODataJsonLightParameterDeserializer_NullCollectionExpected", "PrimitiveValue", "123"), this.ExceptionVerifier); this.Assert.AreEqual(ODataParameterReaderState.Exception, reader.State, "Unexpected first parameter state."); reader = this.CreateParameterReaderForRequestOrResponse(model, functionImport_Complex, testConfiguration, "{\"complex\":null}"); reader.Read(); this.Assert.AreEqual("complex", reader.Name, "Unexpected first parameter name."); this.Assert.IsNull(reader.Value, "Unexpected first parameter value."); this.Assert.AreEqual(ODataParameterReaderState.Resource, reader.State, "Unexpected first parameter state."); }); }
public static IEdmModel GetEdmModel(IEdmModel edmModel, ODataPath path) { if (path.FirstSegment is EntitySetSegment entitySetSegment) { IEdmEntitySet entitySet = OeEdmClrHelper.GetEntitySet(edmModel, entitySetSegment.EntitySet.Name); return(edmModel.GetEdmModel(entitySet.Container)); } if (path.FirstSegment is OperationImportSegment importSegment) { IEdmOperationImport operationImport = importSegment.OperationImports.Single(); operationImport = edmModel.FindDeclaredOperationImports(operationImport.Name).Single(); return(edmModel.GetEdmModel(operationImport.Container)); } throw new InvalidOperationException("Not supported segment type " + path.FirstSegment.GetType().FullName); }
/// <summary> /// Create the Swagger path for the Edm operation import. /// </summary> /// <param name="operationImport">The Edm operation import</param> /// <returns>The <see cref="Newtonsoft.Json.Linq.JObject" /> represents the related Edm operation import.</returns> public static PathItem CreateSwaggerPathForOperationImport(IEdmOperationImport operationImport) { if (operationImport == null) { return(new PathItem()); } var isFunctionImport = operationImport is IEdmFunctionImport; var swaggerParameters = new List <Parameter>(); foreach (var parameter in operationImport.Operation.Parameters) { swaggerParameters.Parameter(parameter.Name, isFunctionImport ? "path" : "body", "parameter: " + parameter.Name, parameter.Type.Definition); } var swaggerResponses = new Dictionary <string, Response>(); if (operationImport.Operation.ReturnType == null) { swaggerResponses.Response("204", "Empty response"); } else { swaggerResponses.Response("200", "Response from " + operationImport.Name, operationImport.Operation.ReturnType.Definition); } var swaggerOperationImport = new Operation() .Summary("Call operation import " + operationImport.Name) .OperationId(operationImport.Name + (isFunctionImport ? "_FunctionImportGet" : "_ActionImportPost")) .Description("Call operation import " + operationImport.Name) .Tags(isFunctionImport ? "Function Import" : "Action Import"); if (swaggerParameters.Count > 0) { swaggerOperationImport.Parameters(swaggerParameters); } swaggerOperationImport.Responses(swaggerResponses.DefaultErrorResponse()); return(isFunctionImport ? new PathItem { get = swaggerOperationImport } : new PathItem { post = swaggerOperationImport }); }
public void ParameterReaderIgnoreMissingMultipleNullableParameterTest() { IEdmModel model = TestModels.BuildModelWithFunctionImport(); IEdmOperationImport functionImport = model.FindEntityContainer("TestContainer").FindOperationImports("FunctionImport_MultipleNullableParameters").Single(); var parameterValues = new[] { "\"p1\" : \"AAEC\"", "\"p2\" : true", "\"p3\" : 1", "\"p5\" : \"2012-05-25T09:00:42.5018138-07:00\"", "\"p6\" : 79228162514264337593543950335", "\"p7\" : \"INF\"", "\"p8\" : \"446806b7-7d7f-4e60-9e2b-bc28d9671a4f\"", "\"p9\" : \"32767\"", "\"p10\" : 2147483647", "\"p11\" : 0", "\"p12\" : \"1\"", "\"p13\" : \"0.01\"", "\"p14\" : { type: \"Point\", coordinates: [ -122.107711791992, 47.6472206115723 ], crs: { type: \"name\", properties: { name: \"EPSG:4326\" } } }", "\"p15\" : \"foo\"", "\"p16\" : { @odata.type: \"#TestModel.ComplexTypeWithNullableProperties\", IntegerProperty: 1 }", "\"p17\" : \"enumType1_value2\"", // supports reading enum values without validation }; var multipleParameterTestCases = parameterValues.Combinations(false, new[] { 1, 2, 16 }).ToArray(); this.CombinatorialEngineProvider.RunCombinations( multipleParameterTestCases, this.ReaderTestConfigurationProvider.JsonLightFormatConfigurations.Where(c => c.IsRequest == true), (testCase, testConfiguration) => { string payload = "{" + string.Join(",", testCase) + "}"; var reader = this.CreateParameterReaderForRequestOrResponse(model, functionImport, testConfiguration, payload); foreach (var parameter in testCase) { this.Assert.IsTrue(reader.Read(), "Read() should not fail for payload " + payload); this.Assert.AreEqual(ODataParameterReaderState.Value, reader.State, "State should be Value."); } this.Assert.IsFalse(reader.Read(), "Read() should fail after reading all parameters"); this.Assert.AreEqual(ODataParameterReaderState.Completed, reader.State, "State should be Complete."); }); }
public void FindOperationImportInExtendedContainer() { string mainModelxml = @"<?xml version=""1.0"" encoding=""utf-16""?> <edmx:Edmx Version=""4.0"" xmlns:edmx=""http://docs.oasis-open.org/odata/ns/edmx""> <edmx:Reference Uri=""http://host/schema/Location.xml""> <edmx:Include Namespace=""Namespace1"" Alias=""A1"" /> </edmx:Reference> <edmx:DataServices> <Schema Namespace=""Namespace0"" xmlns=""http://docs.oasis-open.org/odata/ns/edm""> <EntityContainer Name=""DefaultContainer0"" Extends=""Namespace1.Container_sub""> </EntityContainer> </Schema> </edmx:DataServices> </edmx:Edmx>"; string model1xml = @"<?xml version=""1.0"" encoding=""utf-16""?> <edmx:Edmx Version=""4.0"" xmlns:edmx=""http://docs.oasis-open.org/odata/ns/edmx""> <edmx:DataServices> <Schema Namespace=""Namespace1"" xmlns=""http://docs.oasis-open.org/odata/ns/edm""> <Function Name=""Function1""> <ReturnType Type=""Edm.Int16"" /> </Function> <EntityContainer Name=""Container_sub""> <FunctionImport Name=""FunctionImport1"" Function=""Namespace1.Function1""/> </EntityContainer> </Schema> </edmx:DataServices> </edmx:Edmx>"; IEnumerable <EdmError> errors; IEdmModel model1; bool parsed = CsdlReader.TryParse(XmlReader.Create(new StringReader(model1xml)), out model1, out errors); Assert.IsTrue(parsed); IEdmModel mainModel; parsed = CsdlReader.TryParse(XmlReader.Create(new StringReader(mainModelxml)), new IEdmModel[] { model1 }, out mainModel, out errors); Assert.IsTrue(parsed); IEnumerable <IEdmOperationImport> operationImports1 = mainModel.FindDeclaredOperationImports("FunctionImport1"); IEdmOperationImport operationImport1 = operationImports1.Single(); IEdmOperationImport operationImport1FromContainer = mainModel.EntityContainer.FindOperationImportsExtended("FunctionImport1").Single(); Assert.AreEqual("FunctionImport1", operationImport1.Name); }
/// <summary> /// Create the Swagger path for the Edm operation import. /// </summary> /// <param name="operationImport">The Edm operation import</param> /// <returns>The <see cref="Newtonsoft.Json.Linq.JObject"/> represents the related Edm operation import.</returns> public static JObject CreateSwaggerPathForOperationImport(IEdmOperationImport operationImport) { if (operationImport == null) { return(new JObject()); } bool isFunctionImport = operationImport is IEdmFunctionImport; JArray swaggerParameters = new JArray(); foreach (var parameter in operationImport.Operation.Parameters) { swaggerParameters.Parameter(parameter.Name, isFunctionImport ? "path" : "body", "parameter: " + parameter.Name, parameter.Type.Definition); } JObject swaggerResponses = new JObject(); if (operationImport.Operation.ReturnType == null) { swaggerResponses.Response("204", "Empty response"); } else { swaggerResponses.Response("200", "Response from " + operationImport.Name, operationImport.Operation.ReturnType.Definition); } JObject swaggerOperationImport = new JObject() .Summary("Call operation import " + operationImport.Name) .OperationId(operationImport.Name + (isFunctionImport ? "_FunctionImportGet" : "_ActionImportPost")) .Description("Call operation import " + operationImport.Name) .Tags(isFunctionImport ? "Function Import" : "Action Import"); if (swaggerParameters.Count > 0) { swaggerOperationImport.Parameters(swaggerParameters); } swaggerOperationImport.Responses(swaggerResponses.DefaultErrorResponse()); return(new JObject() { { isFunctionImport ? "get" : "post", swaggerOperationImport } }); }
public void BuildPathWithFunctionImport() { ODataUri odataUri = new ODataUri(); odataUri.ServiceRoot = new Uri("http://gobbledygook/"); IEdmOperationImport functionImport = HardCodedTestModel.TestModel.EntityContainer.FindOperationImports("GetPet1").Single(); IEdmEntitySetReferenceExpression reference = functionImport.EntitySet as IEdmEntitySetReferenceExpression; OperationSegmentParameter[] parameters = new OperationSegmentParameter[] { new OperationSegmentParameter("id", new ConstantNode(1, "1")) }; odataUri.Path = new ODataPath(new OperationImportSegment( new IEdmOperationImport[] { functionImport }, reference.ReferencedEntitySet, parameters)); ODataUriBuilder odataUriBuilder = new ODataUriBuilder(ODataUrlConventions.Default, odataUri); Uri actual = odataUriBuilder.BuildUri(); Assert.Equal(new Uri("http://gobbledygook/GetPet1(id=1)"), actual); }
public void BuildPathWithFunctionImport() { ODataUri odataUri = new ODataUri(); odataUri.ServiceRoot = new Uri("http://gobbledygook/"); IEdmOperationImport functionImport = HardCodedTestModel.TestModel.EntityContainer.FindOperationImports("GetPet1").Single(); IEdmEntitySetBase entitySet; Assert.True(functionImport.TryGetStaticEntitySet(HardCodedTestModel.TestModel, out entitySet)); OperationSegmentParameter[] parameters = { new OperationSegmentParameter("id", new ConstantNode(1, "1")) }; odataUri.Path = new ODataPath(new OperationImportSegment( new [] { functionImport }, entitySet, parameters)); Uri actual = odataUri.BuildUri(ODataUrlKeyDelimiter.Parentheses); Assert.Equal(new Uri("http://gobbledygook/GetPet1(id=1)"), actual); }
internal override void WriteOperationImportAttributes(IEdmOperationImport operationImport, string operationAttributeName) { this.WriteRequiredAttribute(CsdlConstants.Attribute_Name, operationImport.Name, EdmValueWriter.StringAsXml); this.WriteRequiredAttribute(operationAttributeName, operationImport.Operation.FullName(), EdmValueWriter.StringAsXml); if (operationImport.EntitySet != null) { var pathExpression = operationImport.EntitySet as IEdmPathExpression; if (pathExpression != null) { this.WriteOptionalAttribute(CsdlConstants.Attribute_EntitySet, pathExpression.PathSegments, PathAsXml); } else { throw new InvalidOperationException(Strings.EdmModel_Validator_Semantic_OperationImportEntitySetExpressionIsInvalid(operationImport.Name)); } } }
public IAsyncEnumerable <Object> GetAsyncEnumerable(ODataUri odataUri, Stream?requestStream, OeRequestHeaders headers, Object dataContext, CancellationToken cancellationToken, out bool isScalar) { isScalar = true; var importSegment = (OperationImportSegment)odataUri.Path.LastSegment; IReadOnlyList <KeyValuePair <String, Object?> > parameters = OeOperationHelper.GetParameters(_edmModel, importSegment, odataUri.ParameterAliasNodes, requestStream, headers.ContentType); IEdmOperationImport operationImport = importSegment.OperationImports.Single(); IEdmEntitySet? entitySet = OeOperationHelper.GetEntitySet(operationImport); if (entitySet == null) { if (operationImport.Operation.ReturnType == null) { return(_dataAdapter.OperationAdapter.ExecuteProcedureNonQuery(dataContext, operationImport.Name, parameters)); } Type returnType = _edmModel.GetClrType(operationImport.Operation.ReturnType.Definition); if (operationImport.Operation.ReturnType.IsCollection()) { isScalar = false; returnType = typeof(IEnumerable <>).MakeGenericType(returnType); } if (_edmModel.IsDbFunction(operationImport.Operation)) { return(_dataAdapter.OperationAdapter.ExecuteFunctionPrimitive(dataContext, operationImport.Name, parameters, returnType, cancellationToken)); } else { return(_dataAdapter.OperationAdapter.ExecuteProcedurePrimitive(dataContext, operationImport.Name, parameters, returnType, cancellationToken)); } } isScalar = false; Db.OeEntitySetAdapter entitySetAdapter = _dataAdapter.EntitySetAdapters.Find(entitySet); if (_edmModel.IsDbFunction(operationImport.Operation)) { return(_dataAdapter.OperationAdapter.ExecuteFunctionReader(dataContext, operationImport.Name, parameters, entitySetAdapter)); } else { return(_dataAdapter.OperationAdapter.ExecuteProcedureReader(dataContext, operationImport.Name, parameters, entitySetAdapter)); } }
public void Cant_SetFunctionTitle_OnNonBindableFunctions() { // Arrange ODataModelBuilder builder = new ODataModelBuilder(); FunctionConfiguration function = builder.Function("MyFunction"); function.Returns <int>(); function.Title = "My Function"; // Act IEdmModel model = builder.GetEdmModel(); IEdmOperationImport functionImport = model.EntityContainer.OperationImports().OfType <IEdmFunctionImport>().Single(); Assert.NotNull(functionImport); OperationTitleAnnotation functionTitleAnnotation = model.GetOperationTitleAnnotation(functionImport.Operation); // Assert Assert.Null(functionTitleAnnotation); }
private IEdmOperationImport FindParameterizedOperationImport(string parameterizedName, Func <string, IEnumerable <IEdmOperationImport> > findFunctions, Func <IEnumerable <IEdmOperationImport>, IEdmOperationImport> ambiguityCreator) { IEnumerable <IEdmOperationImport> matchingFunctions = findFunctions(parameterizedName); if (matchingFunctions.Count() == 0) { return(null); } if (matchingFunctions.Count() == 1) { return(matchingFunctions.First()); } else { IEdmOperationImport ambiguous = ambiguityCreator(matchingFunctions); return(ambiguous); } }
/// <summary> /// Gets the target entity set for the given operation import. /// </summary> /// <param name="operationImport">The operation import.</param> /// <param name="sourceEntitySet">The source entity set.</param> /// <param name="model">The model.</param> /// <returns>The target entity set of the operation import or null if it could not be determined.</returns> internal static IEdmEntitySetBase GetTargetEntitySet(this IEdmOperationImport operationImport, IEdmEntitySetBase sourceEntitySet, IEdmModel model) { IEdmEntitySet targetEntitySet; if (operationImport.TryGetStaticEntitySet(out targetEntitySet)) { return(targetEntitySet); } if (sourceEntitySet == null) { return(null); } if (operationImport.Operation.IsBound && operationImport.Operation.Parameters.Any()) { IEdmOperationParameter parameter; IEnumerable <IEdmNavigationProperty> path; IEnumerable <EdmError> errors; if (operationImport.TryGetRelativeEntitySetPath(model, out parameter, out path, out errors)) { IEdmEntitySetBase currentEntitySet = sourceEntitySet; foreach (var navigation in path) { currentEntitySet = currentEntitySet.FindNavigationTarget(navigation) as IEdmEntitySetBase; if (currentEntitySet == null || currentEntitySet is IEdmUnknownEntitySet) { return(currentEntitySet); } } return(currentEntitySet); } else { bool foundSyntaxError = !errors.Any(e => e.ErrorCode == EdmErrorCode.InvalidPathFirstPathParameterNotMatchingFirstParameterName); ExceptionUtil.ThrowSyntaxErrorIfNotValid(foundSyntaxError); } } return(null); }
private IEdmOperationImport CreateAmbiguousOperationImport(IEnumerable <IEdmOperationImport> operations) { Debug.Assert(operations.Count() > 1, "Should not make an ambiguous thing with fewer than two items"); IEnumerator <IEdmOperationImport> operationEnumerator = operations.GetEnumerator(); operationEnumerator.MoveNext(); IEdmOperationImport first = operationEnumerator.Current; operationEnumerator.MoveNext(); IEdmOperationImport second = operationEnumerator.Current; AmbiguousOperationImportBinding ambiguous = new AmbiguousOperationImportBinding(first, second); while (operationEnumerator.MoveNext()) { ambiguous.AddBinding(operationEnumerator.Current); } return(ambiguous); }
/// <summary> /// Creates an <see cref="ODataParameterWriter" /> to write a parameter payload. /// </summary> /// <param name="functionImport">The function import whose parameters will be written.</param> /// <returns>The created parameter writer.</returns> public ODataParameterWriter CreateODataParameterWriter(IEdmOperationImport functionImport) { IEdmOperation operation = functionImport != null ? functionImport.Operation : null; if (this.testConfiguration.Synchronous) { return(new ODataParameterWriterTestWrapper(this.messageWriter.CreateODataParameterWriter(operation), this.testConfiguration)); } else { #if SILVERLIGHT throw new TaupoNotSupportedException("This test is not supported in aSynchronous mode in Silverlight"); #else return(this.messageWriter.CreateODataParameterWriterAsync(operation) .ContinueWith(task => new ODataParameterWriterTestWrapper(task.Result, this.testConfiguration), TaskContinuationOptions.ExecuteSynchronously) .WaitForResult()); #endif } }
public void CreateResponseForEdmFunctionReturnCorrectResponses(bool isFunctionImport) { // Arrange string operationName = "GetPersonWithMostFriends"; IEdmModel model = EdmModelHelper.TripServiceModel; ODataContext context = new ODataContext(model); // Act OpenApiResponses responses; if (isFunctionImport) { IEdmOperationImport operationImport = model.EntityContainer.OperationImports().First(o => o.Name == operationName); Assert.NotNull(operationImport); // guard responses = context.CreateResponses(operationImport); } else { IEdmOperation operation = model.SchemaElements.OfType <IEdmOperation>().First(o => o.Name == operationName); Assert.NotNull(operation); // guard responses = context.CreateResponses(operation); } // Assert Assert.NotNull(responses); Assert.NotEmpty(responses); Assert.Equal(2, responses.Count); Assert.Equal(new string[] { "200", "default" }, responses.Select(r => r.Key)); OpenApiResponse response = responses["200"]; Assert.NotNull(response.Content); OpenApiMediaType mediaType = response.Content["application/json"]; Assert.NotNull(mediaType.Schema); Assert.True(mediaType.Schema.Nullable); Assert.Null(mediaType.Schema.Reference); Assert.NotNull(mediaType.Schema.AnyOf); var anyOf = Assert.Single(mediaType.Schema.AnyOf); Assert.Equal("Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person", anyOf.Reference.Id); }
/// <summary> /// Creates an <see cref="ODataCollectionReader" /> to read a collection of primitive or complex values (as result of a service operation invocation). /// </summary> /// <param name="producingFunctionImport">The function import producing the collection to be read.</param> /// <returns>The created collection reader.</returns> public ODataCollectionReader CreateODataCollectionReader(IEdmOperationImport producingFunctionImport) { IEdmTypeReference itemTypeReference = ((IEdmCollectionTypeReference)producingFunctionImport.Operation.ReturnType).GetCollectionItemType(); if (this.testConfiguration.Synchronous) { return(new ODataCollectionReaderTestWrapper(this.messageReader.CreateODataCollectionReader(itemTypeReference), this.testConfiguration)); } else { #if SILVERLIGHT || WINDOWS_PHONE throw new PlatformNotSupportedException("Asynchronous reading is only supported on desktop"); #else return(this.messageReader.CreateODataCollectionReaderAsync(itemTypeReference).ContinueWith( task => new ODataCollectionReaderTestWrapper(task.Result, this.testConfiguration), TaskContinuationOptions.ExecuteSynchronously) .WaitForResult()); #endif } }
/// <summary> /// Creates an <see cref="ODataParameterReader" /> to read the parameters for <paramref name="expectedFunctionImport"/>. /// </summary> /// <param name="expectedFunctionImport">The expected function import whose parameters are being read.</param> /// <returns>The created parameter reader.</returns> public ODataParameterReaderTestWrapper CreateODataParameterReader(IEdmOperationImport expectedFunctionImport) { IEdmOperation operation = expectedFunctionImport != null ? expectedFunctionImport.Operation : null; if (this.testConfiguration.Synchronous) { return(new ODataParameterReaderTestWrapper(this.messageReader.CreateODataParameterReader(operation), this.testConfiguration)); } else { #if SILVERLIGHT || WINDOWS_PHONE throw new PlatformNotSupportedException("Asynchronous reading is only supported on desktop"); #else return(this.messageReader.CreateODataParameterReaderAsync(operation).ContinueWith( task => new ODataParameterReaderTestWrapper(task.Result, this.testConfiguration), TaskContinuationOptions.ExecuteSynchronously) .WaitForResult()); #endif } }
/// <summary> /// Get the Uri Swagger path for Edm operation import. /// </summary> /// <param name="routePrefix">The route prefix.</param> /// <param name="operationImport">The Edm operation import.</param> /// <returns> /// The <see cref="string" /> path represents the related Edm operation import. /// </returns> public static string GetPathForOperationImport(string routePrefix, IEdmOperationImport operationImport) { Contract.Requires(routePrefix != null); Contract.Requires(operationImport != null); var swaggerOperationImportPath = routePrefix.AppendPathSegment(operationImport.Name) + "("; if (operationImport.IsFunctionImport()) { swaggerOperationImportPath = operationImport.Operation?.Parameters?.Aggregate(swaggerOperationImportPath, (current, parameter) => current + parameter.Name + "=" + "{" + parameter.Name + "},"); } Contract.Assume(swaggerOperationImportPath != null); if (swaggerOperationImportPath.EndsWith(",", StringComparison.Ordinal)) { swaggerOperationImportPath = swaggerOperationImportPath.Substring(0, swaggerOperationImportPath.Length - 1); } swaggerOperationImportPath += ")"; return(swaggerOperationImportPath); }
static string GetPathForOperationImport(IEdmOperationImport operationImport) { string swaggerOperationImportPath = "/" + operationImport.Name + "("; if (operationImport.IsFunctionImport()) { foreach (var parameter in operationImport.Operation.Parameters) { swaggerOperationImportPath += parameter.Name + "=" + "{" + parameter.Name + "},"; } } if (swaggerOperationImportPath.EndsWith(",")) { swaggerOperationImportPath = swaggerOperationImportPath.Substring(0, swaggerOperationImportPath.Length - 1); } swaggerOperationImportPath += ")"; return(swaggerOperationImportPath); }
public void ParameterReaderIgnoreMissingNullableParameterTest() { IEdmModel model = TestModels.BuildModelWithFunctionImport(); IEdmOperationImport functionImport = model.FindEntityContainer("TestContainer").FindOperationImports("FunctionImport_NullablePrimitive").First(); this.CombinatorialEngineProvider.RunCombinations( this.ReaderTestConfigurationProvider.JsonLightFormatConfigurations.Where(c => c.IsRequest == true), (testConfiguration) => { // Reading an empty payload should not fail ODataParameterReaderTestWrapper reader = this.CreateParameterReaderForRequestOrResponse(model, functionImport, testConfiguration); this.Assert.IsFalse(reader.Read(), "Read() should return false on an empty payload."); this.Assert.AreEqual(ODataParameterReaderState.Completed, reader.State, "State should be completed."); // Reading a parameter payload with no parameter should not fail reader = this.CreateParameterReaderForRequestOrResponse(model, functionImport, testConfiguration, "{}"); this.Assert.IsFalse(reader.Read(), "Read() should return false on a parameter payload with no parameter."); this.Assert.AreEqual(ODataParameterReaderState.Completed, reader.State, "State should be completed."); }); }
/// <summary> /// Initializes a new instance of the <see cref="FunctionImportSegmentTemplate" /> class. /// </summary> /// <param name="segment">The input function import segment.</param> public FunctionImportSegmentTemplate(OperationImportSegment segment) { if (segment == null) { throw Error.ArgumentNull(nameof(segment)); } IEdmOperationImport operationImport = segment.OperationImports.First(); if (!operationImport.IsFunctionImport()) { throw new ODataException(Error.Format(SRResources.SegmentShouldBeKind, "FunctionImport", "FunctionImportSegmentTemplate")); } FunctionImport = (IEdmFunctionImport)operationImport; NavigationSource = segment.EntitySet; ParameterMappings = segment.Parameters.BuildParameterMappings(operationImport.Name); }
public static IEdmModel GetEdmModel(this IEdmModel edmModel, ODataPath path) { if (path.FirstSegment is EntitySetSegment entitySetSegment) { return(edmModel.GetEdmModel(entitySetSegment.EntitySet)); } if (path.FirstSegment is OperationImportSegment importSegment) { IEdmOperationImport operationImport = importSegment.OperationImports.Single(); return(edmModel.GetEdmModel(operationImport.Container)); } if (path.FirstSegment == null) { throw new InvalidOperationException("Invalid path first sgment is null"); } throw new InvalidOperationException("Not supported segment type " + path.FirstSegment.GetType().FullName); }
/// <summary> /// Write payload kind to message. /// </summary> /// <param name="messageWriter">Message writer to write payload to.</param> /// <param name="payloadKind">The kind of payload we are writing.</param> /// <param name="payload">The payload to write.</param> /// <param name="functionImport">Function import whose parameters are to be written when the payload kind is Parameters.</param> /// <returns>The object read after writing.</returns> public ODataItem WriteMessage(ODataMessageWriterTestWrapper messageWriter, ODataMessageReaderTestWrapper messageReader, ODataPayloadKind payloadKind, object payload, IEdmOperationImport functionImport = null) { ExceptionUtilities.CheckArgumentNotNull(messageWriter, "messageWriter"); ExceptionUtilities.CheckArgumentNotNull(messageReader, "messageReader"); switch (payloadKind) { case ODataPayloadKind.Feed: this.WriteTopLevelFeed(messageWriter, messageReader, (ODataFeed)payload); break; case ODataPayloadKind.Entry: this.WriteTopLevelEntry(messageWriter, messageReader, (ODataEntry)payload); break; default: ExceptionUtilities.Assert(false, "The payload kind '{0}' is not yet supported by ObjectModelWriteReadStreamer.", payloadKind); break; } return readItems.SingleOrDefault(); }
/// <summary> /// Gets the parameter value. /// </summary> /// <param name="segment">The function import segment</param> /// <param name="parameterName">The parameter name</param> /// <returns>The parameter value</returns> public static object GetParameterValue(this OperationImportSegment segment, string parameterName) { if (segment == null) { throw Error.ArgumentNull("segment"); } if (String.IsNullOrEmpty(parameterName)) { throw Error.ArgumentNullOrEmpty("parameterName"); } if (!segment.OperationImports.Any() || !segment.OperationImports.First().IsFunctionImport()) { throw Error.Argument("segment", SRResources.OperationImportSegmentMustBeFunction); } OperationSegmentParameter parameter = segment.Parameters.FirstOrDefault(p => p.Name == parameterName); if (parameter == null) { throw Error.Argument("parameterName", SRResources.FunctionParameterNotFound, parameterName); } object value = TranslateNode(parameter.Value); if (value == null || value is ODataNullValue) { IEdmOperationImport operation = segment.OperationImports.First(); IEdmOperationParameter operationParameter = operation.Operation.Parameters.First(p => p.Name == parameterName); Contract.Assert(operationParameter != null); if (!operationParameter.Type.IsNullable) { throw new ODataException(String.Format(CultureInfo.InvariantCulture, SRResources.NullOnNonNullableFunctionParameter, operationParameter.Type.FullName())); } } return(value); }
/// <summary> /// Checks if the operation import should be included. /// </summary> /// <param name="operationImport">Operation import.</param> /// <param name="excludedTypes">A collection of excluded types.</param> /// <returns>true if the operation import should be included, otherwise false.</returns> public bool IsOperationImportIncluded(IEdmOperationImport operationImport, ICollection <string> excludedTypes) { IEnumerable <IEdmOperationParameter> parameters = operationImport.Operation.Parameters; foreach (var parameter in parameters) { if (excludedTypes.Contains(parameter.Type.FullName())) { return(false); } } string returnType = operationImport.Operation.ReturnType?.FullName(); if (excludedTypes.Contains(returnType)) { return(false); } return(true); }
private static string GetEntitySetString(IEdmOperationImport operationImport) { if (operationImport.EntitySet != null) { var entitySetReference = operationImport.EntitySet as IEdmEntitySetReferenceExpression; if (entitySetReference != null) { return(entitySetReference.ReferencedEntitySet.Name); } else { var pathExpression = operationImport.EntitySet as IEdmPathExpression; if (pathExpression != null) { return(EdmModelCsdlSchemaWriter.PathAsXml(pathExpression.Path)); } } } return(null); }
/// <summary> /// Creates an <see cref="ODataParameterReader" /> to read the parameters for <paramref name="expectedFunctionImport"/>. /// </summary> /// <param name="expectedFunctionImport">The expected function import whose parameters are being read.</param> /// <returns>The created parameter reader.</returns> public ODataParameterReaderTestWrapper CreateODataParameterReader(IEdmOperationImport expectedFunctionImport) { IEdmOperation operation = expectedFunctionImport != null ? expectedFunctionImport.Operation : null; if (this.testConfiguration.Synchronous) { return new ODataParameterReaderTestWrapper(this.messageReader.CreateODataParameterReader(operation), this.testConfiguration); } else { #if SILVERLIGHT || WINDOWS_PHONE throw new PlatformNotSupportedException("Asynchronous reading is only supported on desktop"); #else return this.messageReader.CreateODataParameterReaderAsync(operation).ContinueWith( task => new ODataParameterReaderTestWrapper(task.Result, this.testConfiguration), TaskContinuationOptions.ExecuteSynchronously) .WaitForResult(); #endif } }
/// <summary> /// Reads an <see cref="ODataProperty"/> as message payload. /// </summary> /// <param name="producingFunctionImport">The function import producing the collection to be read.</param> /// <returns>The property read from the payload.</returns> public ODataProperty ReadProperty(IEdmOperationImport producingFunctionImport) { if (this.testConfiguration.Synchronous) { return this.messageReader.ReadProperty(producingFunctionImport.Operation.ReturnType); } else { #if SILVERLIGHT || WINDOWS_PHONE throw new PlatformNotSupportedException("Asynchronous reading is only supported on desktop"); #else return this.messageReader.ReadPropertyAsync(producingFunctionImport.Operation.ReturnType).WaitForResult(); #endif } }
static string GetPathForOperationImport(IEdmOperationImport operationImport) { string swaggerOperationImportPath = "/" + operationImport.Name + "("; if (operationImport.IsFunctionImport()) { foreach (var parameter in operationImport.Operation.Parameters) { swaggerOperationImportPath += parameter.Name + "=" + "{" + parameter.Name + "},"; } } if (swaggerOperationImportPath.EndsWith(",")) { swaggerOperationImportPath = swaggerOperationImportPath.Substring(0, swaggerOperationImportPath.Length - 1); } swaggerOperationImportPath += ")"; return swaggerOperationImportPath; }
/// <summary> /// Creates an <see cref="ODataCollectionReader" /> to read a collection of primitive or complex values (as result of a service operation invocation). /// </summary> /// <param name="producingFunctionImport">The function import producing the collection to be read.</param> /// <returns>The created collection reader.</returns> public ODataCollectionReader CreateODataCollectionReader(IEdmOperationImport producingFunctionImport) { IEdmTypeReference itemTypeReference = ((IEdmCollectionTypeReference)producingFunctionImport.Operation.ReturnType).GetCollectionItemType(); if (this.testConfiguration.Synchronous) { return new ODataCollectionReaderTestWrapper(this.messageReader.CreateODataCollectionReader(itemTypeReference), this.testConfiguration); } else { #if SILVERLIGHT || WINDOWS_PHONE throw new PlatformNotSupportedException("Asynchronous reading is only supported on desktop"); #else return this.messageReader.CreateODataCollectionReaderAsync(itemTypeReference).ContinueWith( task => new ODataCollectionReaderTestWrapper(task.Result, this.testConfiguration), TaskContinuationOptions.ExecuteSynchronously) .WaitForResult(); #endif } }
public static void VerifyServiceOperationsAreEqual(IEdmOperationImport expected, IEdmOperationImport actual, AssertionHandler assert) { if (expected == null) { assert.IsNull(actual, "The service operation should be null."); } else { assert.IsNotNull(actual, "The service operation should not be null."); assert.AreEqual(expected.Name, actual.Name, "The service operation names are different."); } }
private static void ValidateProcedureEntitySetPath(IEdmModel model, IEdmOperationImport operationImport, ProcedureConfiguration procedure) { IEdmOperationParameter procedureParameter; IEnumerable<IEdmNavigationProperty> navPath; IEnumerable<EdmError> edmErrors; if (procedure.EntitySetPath != null && !operationImport.TryGetRelativeEntitySetPath(model, out procedureParameter, out navPath, out edmErrors)) { throw Error.InvalidOperation(SRResources.ProcedureHasInvalidEntitySetPath, String.Join("/", procedure.EntitySetPath), procedure.FullyQualifiedName); } }
/// <summary> /// Creates an ODataParameterReader with the given input. /// </summary> /// <param name="model">Model containing the function import.</param> /// <param name="functionImport">function import whose parameters are being read.</param> /// <param name="testConfiguration">test configuration.</param> /// <param name="payload">optional parameter payload.</param> /// <returns>Returns the created ODataParameterReader</returns> internal static ODataParameterReaderTestWrapper CreateODataParameterReader(IEdmModel model, IEdmOperationImport functionImport, ReaderTestConfiguration testConfiguration, string payload = null) { // TODO: ODataLib test item: Add new ODataPayloadElement for parameters payload // Once the bug is fixed, we should generate the parameters payload from the new ODataPayloadElement to make // tests in this file format agnostic. TestStream messageStream; if (payload != null) { messageStream = new TestStream(new MemoryStream(Encoding.UTF8.GetBytes(payload))); } else { messageStream = new TestStream(); } TestMessage message = TestReaderUtils.CreateInputMessageFromStream(messageStream, testConfiguration, ODataPayloadKind.Parameter, /*customContentTypeHeader*/null, /*urlResolver*/null); ODataMessageReaderTestWrapper messageReader = TestReaderUtils.CreateMessageReader(message, model, testConfiguration); return messageReader.CreateODataParameterReader(functionImport); }
/// <summary> /// Read parameters as the message content. /// </summary> /// <param name="messageReader">The message reader to use for reading.</param> /// <param name="functionImport">The function import to pass to the parameter reader.</param> /// <returns>A ComplexInstance representing parameters.</returns> public object ReadParameters(ODataMessageReaderTestWrapper messageReader, IEdmOperationImport functionImport) { // TODO: ODataLib test item: Add new ODataPayloadElement for parameters payload ODataParameterReader parameterReader = messageReader.CreateODataParameterReader(functionImport); ODataParameters odataParameters = new ODataParameters(); List<ODataProperty> parameters = new List<ODataProperty>(); try { // read the start of the parameters this.assert.AreEqual(ODataParameterReaderState.Start, parameterReader.State, "Reader states don't match."); while (parameterReader.Read()) { switch (parameterReader.State) { case ODataParameterReaderState.Value: odataParameters.Add(new KeyValuePair<string,object>(parameterReader.Name, parameterReader.Value)); break; case ODataParameterReaderState.Entry: ODataReader entryReader = parameterReader.CreateEntryReader(); entryReader.Read(); this.assert.AreEqual(ODataReaderState.EntryStart, entryReader.State, "Reader states don't match."); odataParameters.Add(new KeyValuePair<string,object>(parameterReader.Name, this.ReadEntry(entryReader))); this.assert.AreEqual(ODataReaderState.EntryEnd, entryReader.State, "Reader states don't match."); this.assert.IsFalse(entryReader.Read(), "Read() should return false after EntryEnd."); this.assert.AreEqual(ODataReaderState.Completed, entryReader.State, "Reader states don't match."); break; case ODataParameterReaderState.Feed: ODataReader feedReader = parameterReader.CreateFeedReader(); feedReader.Read(); this.assert.AreEqual(ODataReaderState.FeedStart, feedReader.State, "Reader states don't match."); odataParameters.Add(new KeyValuePair<string,object>(parameterReader.Name, this.ReadFeed(feedReader))); this.assert.AreEqual(ODataReaderState.FeedEnd, feedReader.State, "Reader states don't match."); this.assert.IsFalse(feedReader.Read(), "Read() should return false after EntryEnd."); this.assert.AreEqual(ODataReaderState.Completed, feedReader.State, "Reader states don't match."); break; case ODataParameterReaderState.Collection: ODataCollectionReader collectionReader = parameterReader.CreateCollectionReader(); odataParameters.Add(new KeyValuePair<string,object>(parameterReader.Name, this.ReadCollection(collectionReader))); break; default: this.assert.Fail("Unexpected state: " + parameterReader.State); break; } } this.assert.AreEqual(ODataParameterReaderState.Completed, parameterReader.State, "Reader states don't match."); return odataParameters; } catch (Exception e) { if (ExceptionUtilities.IsCatchable(e)) { this.assert.AreEqual(ODataParameterReaderState.Exception, parameterReader.State, "Expected the reader to be in 'Exception' state."); } throw; } }
private void AddOperationImport(string name, IEdmOperationImport function) { List<IEdmOperationImport> operationImport; if (this.operationImports.TryGetValue(name, out operationImport)) { operationImport.Add(function); } else { this.operationImports.Add(name, new List<IEdmOperationImport>() { function }); } }
/// <summary> /// Creates an ODataParameterReader with the given input. /// </summary> /// <param name="model">Model containing the function import.</param> /// <param name="functionImport">function import whose parameters are being read.</param> /// <param name="testConfiguration">test configuration.</param> /// <param name="payload">optional parameter payload.</param> /// <returns>Returns the created ODataParameterReader</returns> private ODataParameterReaderTestWrapper CreateParameterReaderForRequestOrResponse(IEdmModel model, IEdmOperationImport functionImport, ReaderTestConfiguration testConfiguration, string payload = null) { if (testConfiguration.IsRequest) { return CreateODataParameterReader(model, functionImport, testConfiguration, payload); } else { this.Assert.ExpectedException( () => CreateODataParameterReader(model, functionImport, testConfiguration, payload), ODataExpectedExceptions.ODataException("ODataMessageReader_ParameterPayloadInResponse"), this.ExceptionVerifier); return null; } }
/// <summary> /// Get the Uri Swagger path for Edm operation import. /// </summary> /// <param name="operationImport">The Edm operation import.</param> /// <returns>The <see cref="System.String"/> path represents the related Edm operation import.</returns> public static string GetPathForOperationImport(IEdmOperationImport operationImport) { if (operationImport == null) { return String.Empty; } string swaggerOperationImportPath = "/" + operationImport.Name + "("; if (operationImport.IsFunctionImport()) { foreach (var parameter in operationImport.Operation.Parameters) { swaggerOperationImportPath += parameter.Name + "=" + "{" + parameter.Name + "},"; } } if (swaggerOperationImportPath.EndsWith(",", StringComparison.Ordinal)) { swaggerOperationImportPath = swaggerOperationImportPath.Substring(0, swaggerOperationImportPath.Length - 1); } swaggerOperationImportPath += ")"; return swaggerOperationImportPath; }
/// <summary> /// Writes an <see cref="ODataProperty"/> as message payload. /// </summary> /// <param name="property">The property to write.</param> /// <param name="producingFunctionImport">The function import which return value is being written.</param> public void WriteProperty(ODataProperty property, IEdmOperationImport producingFunctionImport) { if (this.testConfiguration.Synchronous) { this.messageWriter.WriteProperty(property); } else { #if SILVERLIGHT throw new TaupoNotSupportedException("This test is not supported in aSynchronous mode in Silverlight"); #else this.messageWriter.WritePropertyAsync(property).Wait(); #endif } }
static JObject CreateSwaggerPathForOperationImport(IEdmOperationImport operationImport) { JArray swaggerParameters = new JArray(); foreach (var parameter in operationImport.Operation.Parameters) { swaggerParameters.Parameter(parameter.Name, operationImport is IEdmFunctionImport ? "path" : "body", "parameter: " + parameter.Name, parameter.Type.Definition); } JObject swaggerResponses = new JObject(); if (operationImport.Operation.ReturnType == null) { swaggerResponses.Response("204", "Empty response"); } else { swaggerResponses.Response("200", "Response from " + operationImport.Name, operationImport.Operation.ReturnType.Definition); } JObject swaggerOperationImport = new JObject() .Summary("Call operation import " + operationImport.Name) .Description("Call operation import " + operationImport.Name) .Tags(operationImport is IEdmFunctionImport ? "Function Import" : "Action Import"); if (swaggerParameters.Count > 0) { swaggerOperationImport.Parameters(swaggerParameters); } swaggerOperationImport.Responses(swaggerResponses.DefaultErrorResponse()); return new JObject() { {operationImport is IEdmFunctionImport ? "get" : "post", swaggerOperationImport} }; }
private FunctionImport ConvertToTaupoFunctionImport(IEdmOperationImport edmFunctionImport) { var taupoFunctionImport = new FunctionImport(edmFunctionImport.Name); var functionImportReturnType = new FunctionImportReturnType(); var addReturnType = false; if (edmFunctionImport.EntitySet != null) { IEdmEntitySet entitySet; if (edmFunctionImport.TryGetStaticEntitySet(out entitySet)) { functionImportReturnType.EntitySet = new EntitySetReference(entitySet.Name); addReturnType = true; } else { throw new NotSupportedException("Function import with entity set path is not supported."); } } if (edmFunctionImport.Operation.ReturnType != null) { functionImportReturnType.DataType = this.ConvertToTaupoDataType(edmFunctionImport.Operation.ReturnType); addReturnType = true; } if (addReturnType) { taupoFunctionImport.Add(functionImportReturnType); } foreach (var edmFunctionParameter in edmFunctionImport.Operation.Parameters) { FunctionParameter taupoFunctionParameter = this.ConvertToTaupoFunctionParameter(edmFunctionParameter); taupoFunctionImport.Parameters.Add(taupoFunctionParameter); } this.ConvertAnnotationsIntoTaupo(edmFunctionImport, taupoFunctionImport); return taupoFunctionImport; }
internal override IEdmTypeReference GetReturnType(IEdmOperationImport operationImport) { return operationImport == null ? null : operationImport.Operation.ReturnType; }
/// <summary> /// Write payload kind to message. /// </summary> /// <param name="messageWriter">Message writer to write payload to.</param> /// <param name="payloadKind">The kind of payload we are writing.</param> /// <param name="payload">The payload to write.</param> /// <param name="model">The model used for writing the payloads.</param> /// <param name="functionImport">Function import whose parameters are to be written when the payload kind is Parameters.</param> public virtual void WriteMessage( ODataMessageWriterTestWrapper messageWriter, ODataPayloadKind payloadKind, object payload, IEdmModel model = null, IEdmOperationImport functionImport = null) { ExceptionUtilities.CheckArgumentNotNull(messageWriter, "messageReader"); switch (payloadKind) { case ODataPayloadKind.Property: messageWriter.WriteProperty((ODataProperty)payload); break; case ODataPayloadKind.Feed: this.WriteTopLevelFeed(messageWriter, (ODataFeed)payload); break; case ODataPayloadKind.Entry: this.WriteTopLevelEntry(messageWriter, (ODataEntry)payload); break; case ODataPayloadKind.Collection: this.WriteCollection(messageWriter, (ODataCollectionStart)payload); break; case ODataPayloadKind.ServiceDocument: this.WriteServiceDocument(messageWriter, (ODataServiceDocument)payload); break; case ODataPayloadKind.MetadataDocument: this.WriteMetadataDocument(messageWriter); break; case ODataPayloadKind.Error: this.WriteError(messageWriter, (ODataError)payload, true); break; case ODataPayloadKind.EntityReferenceLink: this.WriteEntityReferenceLink(messageWriter, (ODataEntityReferenceLink)payload); break; case ODataPayloadKind.EntityReferenceLinks: this.WriteEntityReferenceLinks(messageWriter, (ODataEntityReferenceLinks)payload); break; case ODataPayloadKind.Value: this.WriteValue(messageWriter, payload); break; case ODataPayloadKind.Batch: // TODO: Have to figure out product representation of batch payloads or perhaps keep it separate throw new NotSupportedException("Batch not supported in ObjectModelToMessageWriter"); case ODataPayloadKind.Parameter: this.WriteParameters(messageWriter, (ODataParameters)payload, functionImport); break; default: ExceptionUtilities.Assert(false, "The payload kind '{0}' is not yet supported by MessageToObjectModelReader.", payloadKind); break; } }
/// <summary> /// Read a collection as the message content. /// </summary> /// <param name="messageReader">The message reader to use for reading.</param> /// <param name="producingFunctionImport">The function import producing the collection to be read.</param> /// <param name="expectedItemTypeReference">The expected item type to pass to the reader.</param> /// <returns>An <see cref="ODataCollectionStart"/>, possibly with annotations.</returns> public object ReadCollection(ODataMessageReaderTestWrapper messageReader, IEdmOperationImport producingFunctionImport, IEdmTypeReference expectedItemTypeReference) { ODataCollectionReader collectionReader = producingFunctionImport != null ? messageReader.CreateODataCollectionReader(producingFunctionImport) : messageReader.CreateODataCollectionReader(expectedItemTypeReference); return this.ReadCollection(collectionReader); }
private void WriteParameters(ODataMessageWriterTestWrapper messageWriter, ODataParameters parameters, IEdmOperationImport functionImport) { ODataParameterWriter parameterWriter = messageWriter.CreateODataParameterWriter(functionImport); parameterWriter.WriteStart(); foreach (var parameter in parameters) { ODataCollectionStart collectionStart = parameter.Value as ODataCollectionStart; ODataFeed feed; ODataEntry entry; if (collectionStart != null) { ODataCollectionWriter collectionWriter = parameterWriter.CreateCollectionWriter(parameter.Key); this.WriteCollection(collectionWriter, collectionStart); collectionWriter.Flush(); } else if ((feed = parameter.Value as ODataFeed) != null) { this.WriteFeed(parameterWriter.CreateFeedWriter(parameter.Key), feed); } else if ((entry = parameter.Value as ODataEntry) != null) { this.WriteEntry(parameterWriter.CreateEntryWriter(parameter.Key), entry); } else { parameterWriter.WriteValue(parameter.Key, parameter.Value); } } parameterWriter.WriteEnd(); parameterWriter.Flush(); }
internal static bool ResolveOperationImportFromList(string identifier, IList<string> parameterNames, IEdmModel model, out IEdmOperationImport matchingOperationImport, ODataUriResolver resolver) { IList<IEdmOperationImport> candidateMatchingOperationImports = null; IList<IEdmActionImport> foundActionImportsWhenLookingForFunctions = new List<IEdmActionImport>(); try { if (parameterNames.Count > 0) { // In this case we have to return a function so filter out actions because the number of parameters > 0. candidateMatchingOperationImports = resolver.ResolveOperationImports(model, identifier).RemoveActionImports(out foundActionImportsWhenLookingForFunctions).FilterFunctionsByParameterNames(parameterNames, resolver.EnableCaseInsensitive).Cast<IEdmOperationImport>().ToList(); } else { candidateMatchingOperationImports = resolver.ResolveOperationImports(model, identifier).ToList(); } } catch (Exception exc) { if (!ExceptionUtils.IsCatchableExceptionType(exc)) { throw; } throw new ODataException(ODataErrorStrings.FunctionOverloadResolver_FoundInvalidOperationImport(identifier), exc); } if (foundActionImportsWhenLookingForFunctions.Count > 0) { throw ExceptionUtil.CreateBadRequestError(ODataErrorStrings.RequestUriProcessor_SegmentDoesNotSupportKeyPredicates(identifier)); } // If any of the things returned are an action, it better be the only thing returned, and there can't be parameters in the URL if (candidateMatchingOperationImports.Any(f => f.IsActionImport())) { if (candidateMatchingOperationImports.Count > 1) { if (candidateMatchingOperationImports.Any(o => o.IsFunctionImport())) { throw new ODataException(ODataErrorStrings.FunctionOverloadResolver_MultipleOperationImportOverloads(identifier)); } else { throw new ODataException(ODataErrorStrings.FunctionOverloadResolver_MultipleActionImportOverloads(identifier)); } } if (parameterNames.Count() != 0) { throw ExceptionUtil.CreateBadRequestError(ODataErrorStrings.RequestUriProcessor_SegmentDoesNotSupportKeyPredicates(identifier)); } matchingOperationImport = candidateMatchingOperationImports.Single(); return true; } // If parameter count is zero and there is one function import whoese parameter count is zero, return this function import. if (candidateMatchingOperationImports.Count > 1 && parameterNames.Count == 0) { candidateMatchingOperationImports = candidateMatchingOperationImports.Where(operationImport => operationImport.Operation.Parameters.Count() == 0).ToList(); } if (candidateMatchingOperationImports.Count == 0) { matchingOperationImport = null; return false; } if (candidateMatchingOperationImports.Count > 1) { throw new ODataException(ODataErrorStrings.FunctionOverloadResolver_MultipleOperationImportOverloads(identifier)); } matchingOperationImport = candidateMatchingOperationImports.Single(); return matchingOperationImport != null; }
/// <summary> /// Invoke the given service operation and returns the results. /// </summary> /// <param name="serviceOperation">service operation to invoke.</param> /// <param name="parameters">value of parameters to pass to the service operation.</param> /// <returns>returns the result of the service operation. If the service operation returns void, then this should return null.</returns> public object InvokeServiceOperation(IEdmOperationImport serviceOperation, object[] parameters) { throw new NotSupportedException(); }
/// <summary> /// Constructor /// </summary> /// <param name="model">The model used to resolve the metadata.</param> /// <param name="payloadElement">The payload element to get the reader metadata for.</param> public ReaderMetadata(IEdmModel model, ODataPayloadElement payloadElement) { var expectedTypeAnnotation = payloadElement.GetAnnotation<ExpectedTypeODataPayloadElementAnnotation>(); // NOTE: we don't require a model for the computation of the expected type (since the expected one might be a primitive type). this.expectedType = GetExpectedType(expectedTypeAnnotation, model); // We need a model for all the other expected reader metadata if (model == null) { // If the annotation specified some model dependent data (basically anything but primitive expected type) // and we don't have a model, we wouldn't be able to correctly represent it here (since we need the model to resolve these) // and thus we should not pass in the expected type alone, as that would be changing the intent of the annotation. if (expectedTypeAnnotation != null && (expectedTypeAnnotation.EntitySet != null || expectedTypeAnnotation.EdmEntitySet != null || expectedTypeAnnotation.FunctionImport != null || expectedTypeAnnotation.ProductFunctionImport != null || expectedTypeAnnotation.MemberProperty != null || expectedTypeAnnotation.EdmProperty != null || expectedTypeAnnotation.NavigationProperty != null || expectedTypeAnnotation.EdmNavigationProperty != null || expectedTypeAnnotation.OpenMemberPropertyName != null || expectedTypeAnnotation.OwningType != null || expectedTypeAnnotation.EdmOwningType != null)) { this.expectedType = null; } return; } ODataPayloadElementType elementType = payloadElement.ElementType; switch (elementType) { case ODataPayloadElementType.EntityInstance: // fall through case ODataPayloadElementType.EntitySetInstance: this.entitySet = GetExpectedEntitySet(expectedTypeAnnotation, model, payloadElement); break; case ODataPayloadElementType.DeferredLink: // fall through case ODataPayloadElementType.LinkCollection: this.navigationProperty = GetExpectedNavigationProperty(expectedTypeAnnotation, model); break; case ODataPayloadElementType.PrimitiveMultiValueProperty: // fall through case ODataPayloadElementType.PrimitiveProperty: // fall through case ODataPayloadElementType.ComplexProperty: // fall through case ODataPayloadElementType.ComplexMultiValueProperty: // fall through case ODataPayloadElementType.EmptyCollectionProperty: this.structuralProperty = GetExpectedStructuralProperty(expectedTypeAnnotation, model); this.functionImport = GetExpectedFunctionImport(expectedTypeAnnotation, model); break; case ODataPayloadElementType.ComplexInstanceCollection: // fall through case ODataPayloadElementType.PrimitiveCollection: // fall through case ODataPayloadElementType.EmptyUntypedCollection: this.functionImport = GetExpectedFunctionImport(expectedTypeAnnotation, model); break; case ODataPayloadElementType.ComplexInstance: // NOTE: this is how we model parameter payloads this.functionImport = GetExpectedFunctionImport(expectedTypeAnnotation, model); break; } }
private static bool TryParseFunctionParameters(string functionName, string parenthesisExpression, ParameterAliasValueAccessor paramAliasAccessor, IEdmOperationImport operationImport, out ICollection<OperationSegmentParameter> parsedSegementParameters) { return TryParseOperationParameters(functionName, parenthesisExpression, paramAliasAccessor, operationImport.Operation, out parsedSegementParameters); }
public CollectionWriterTestCase(CollectionWriterTestDescriptor.ItemDescription[] items, IEdmOperationImport functionImport) { this.items = items; this.functionImport = functionImport; }
/// <summary> /// Tries to find a single matching operation import for the given identifier, and parameters. /// </summary> /// <param name="identifier">The identifier from the URI.</param> /// <param name="parenthesisExpression">The parenthesis expression contianing parameters, if any.</param> /// <param name="configuration">The configuration of the parser.</param> /// <param name="boundParameters">The parsed parameters from the parenthesis expression.</param> /// <param name="matchingFunctionImport">The single matching operation import if one could be determined.</param> /// <returns>Whether or not a matching operation import could be found.</returns> private static bool TryBindingParametersAndMatchingOperationImport(string identifier, string parenthesisExpression, ODataUriParserConfiguration configuration, out ICollection<OperationSegmentParameter> boundParameters, out IEdmOperationImport matchingFunctionImport) { matchingFunctionImport = null; ICollection<FunctionParameterToken> splitParameters = null; if (!String.IsNullOrEmpty(parenthesisExpression)) { if (!FunctionParameterParser.TrySplitOperationParameters(parenthesisExpression, configuration, out splitParameters)) { IEdmOperationImport possibleMatchingOperationImport = null; // Look for an overload that returns an entity collection by the specified name. If so parthensis is just key parameters. if (FunctionOverloadResolver.ResolveOperationImportFromList(identifier, EmptyList, configuration.Model, out possibleMatchingOperationImport, configuration.Resolver)) { IEdmCollectionTypeReference collectionReturnType = possibleMatchingOperationImport.Operation.ReturnType as IEdmCollectionTypeReference; if (collectionReturnType != null && collectionReturnType.ElementType().IsEntity()) { matchingFunctionImport = possibleMatchingOperationImport; boundParameters = null; return true; } else { throw ExceptionUtil.CreateBadRequestError(ODataErrorStrings.RequestUriProcessor_SegmentDoesNotSupportKeyPredicates(identifier)); } } boundParameters = null; return false; } } else { splitParameters = new Collection<FunctionParameterToken>(); } // Resolve the specific overload. if (FunctionOverloadResolver.ResolveOperationImportFromList(identifier, splitParameters.Select(k => k.ParameterName).ToList(), configuration.Model, out matchingFunctionImport, configuration.Resolver)) { var matchingOperation = matchingFunctionImport.Operation; boundParameters = FunctionCallBinder.BindSegmentParameters(configuration, matchingOperation, splitParameters); return true; } boundParameters = null; return false; }
/// <summary> /// Returns the return type of the given operation import. /// </summary> /// <param name="operationImport">The operation import to get the return type from.</param> /// <returns>The <see cref="IEdmType"/> representing the return type fo the <paramref name="operationImport"/>.</returns> internal abstract IEdmTypeReference GetReturnType(IEdmOperationImport operationImport);
private void WriteMethod(OdcmClass odcmClass, IEdmOperation operation, IEdmOperationImport operationImport = null) { var parameters = operation.IsBound ? (from parameter in operation.Parameters where parameter != operation.Parameters.First() select parameter) : (operation.Parameters); var isBoundToCollection = operation.IsBound && operation.Parameters.First().Type.IsCollection(); var odcmMethod = new OdcmMethod(operation.Name, odcmClass.Namespace) { IsComposable = operation.IsFunction() && ((IEdmFunction)operation).IsComposable, IsBoundToCollection = isBoundToCollection, Verbs = operation.IsAction() ? OdcmAllowedVerbs.Post : OdcmAllowedVerbs.Any, Class = odcmClass }; AddVocabularyAnnotations(odcmMethod, operation); if (operationImport != null) { AddVocabularyAnnotations(odcmMethod, operationImport); } odcmClass.Methods.Add(odcmMethod); if (operation.ReturnType != null) { odcmMethod.ReturnType = ResolveType(operation.ReturnType); odcmMethod.IsCollection = operation.ReturnType.IsCollection(); } var callingConvention = operation.IsAction() ? OdcmCallingConvention.InHttpMessageBody : OdcmCallingConvention.InHttpRequestUri; foreach (var parameter in parameters) { var odcmParameter = new OdcmParameter(parameter.Name) { CallingConvention = callingConvention, Type = ResolveType(parameter.Type), IsCollection = parameter.Type.IsCollection(), IsNullable = parameter.Type.IsNullable }; AddVocabularyAnnotations(odcmParameter, parameter); odcmMethod.Parameters.Add(odcmParameter); } }
/// <summary> /// Creates an <see cref="ODataParameterWriter" /> to write a parameter payload. /// </summary> /// <param name="functionImport">The function import whose parameters will be written.</param> /// <returns>The created parameter writer.</returns> public ODataParameterWriter CreateODataParameterWriter(IEdmOperationImport functionImport) { IEdmOperation operation = functionImport != null ? functionImport.Operation : null; if (this.testConfiguration.Synchronous) { return new ODataParameterWriterTestWrapper(this.messageWriter.CreateODataParameterWriter(operation), this.testConfiguration); } else { #if SILVERLIGHT throw new TaupoNotSupportedException("This test is not supported in aSynchronous mode in Silverlight"); #else return this.messageWriter.CreateODataParameterWriterAsync(operation) .ContinueWith(task => new ODataParameterWriterTestWrapper(task.Result, this.testConfiguration), TaskContinuationOptions.ExecuteSynchronously) .WaitForResult(); #endif } }