From d620b220d7dad68faf2f5e2d231869fe5c5ffa78 Mon Sep 17 00:00:00 2001 From: Christof Sprenger Date: Wed, 3 Nov 2021 17:56:18 -0700 Subject: [PATCH 1/2] added marker interface and serialization test --- .../CsdlNavigationPropertyPathExpression.cs | 8 +++- src/Microsoft.OData.Edm/EdmUtil.cs | 5 +++ .../Schema/Interfaces/IEdmPathExpression.cs | 8 ++++ .../EdmNavigationPropertyPathExpression.cs | 2 +- .../Csdl/CsdlWriterTests.cs | 38 +++++++++++++++++++ .../Microsoft.OData.Edm.Tests/EdmUtilTests.cs | 11 ++++++ 6 files changed, 70 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.OData.Edm/Csdl/Parsing/Ast/CsdlNavigationPropertyPathExpression.cs b/src/Microsoft.OData.Edm/Csdl/Parsing/Ast/CsdlNavigationPropertyPathExpression.cs index 267b5d0b62..c44b480040 100644 --- a/src/Microsoft.OData.Edm/Csdl/Parsing/Ast/CsdlNavigationPropertyPathExpression.cs +++ b/src/Microsoft.OData.Edm/Csdl/Parsing/Ast/CsdlNavigationPropertyPathExpression.cs @@ -4,12 +4,16 @@ // //--------------------------------------------------------------------- +using Microsoft.OData.Edm.Vocabularies; +using System.Collections.Generic; + namespace Microsoft.OData.Edm.Csdl.Parsing.Ast { + /// /// Represents a CSDL navigation property Path expression. /// - internal class CsdlNavigationPropertyPathExpression : CsdlPathExpression + internal class CsdlNavigationPropertyPathExpression : CsdlPathExpression, IEdmNavigationPropertyPath { public CsdlNavigationPropertyPathExpression(string path, CsdlLocation location) : base(path, location) @@ -20,5 +24,7 @@ public override EdmExpressionKind ExpressionKind { get { return EdmExpressionKind.NavigationPropertyPath; } } + + IEnumerable IEdmPathExpression.PathSegments => throw new System.NotImplementedException(); } } diff --git a/src/Microsoft.OData.Edm/EdmUtil.cs b/src/Microsoft.OData.Edm/EdmUtil.cs index 198a395950..a440f10b03 100644 --- a/src/Microsoft.OData.Edm/EdmUtil.cs +++ b/src/Microsoft.OData.Edm/EdmUtil.cs @@ -460,6 +460,7 @@ internal static string FullyQualifiedName(IEdmVocabularyAnnotatable element) { IEdmOperationReturn operationReturn; IEdmEnumMember enumMember; + IEdmNavigationPropertyPath edmNavigationPropertyPath; IEdmOperationParameter parameter = element as IEdmOperationParameter; if (parameter != null) { @@ -485,6 +486,10 @@ internal static string FullyQualifiedName(IEdmVocabularyAnnotatable element) return operationName + "/" + CsdlConstants.OperationReturnExternalTarget; } } + else if((edmNavigationPropertyPath = element as IEdmNavigationPropertyPath) != null) + { + return edmNavigationPropertyPath.Path; + } } } } diff --git a/src/Microsoft.OData.Edm/Schema/Interfaces/IEdmPathExpression.cs b/src/Microsoft.OData.Edm/Schema/Interfaces/IEdmPathExpression.cs index 702029a6fa..3363e20410 100644 --- a/src/Microsoft.OData.Edm/Schema/Interfaces/IEdmPathExpression.cs +++ b/src/Microsoft.OData.Edm/Schema/Interfaces/IEdmPathExpression.cs @@ -4,6 +4,7 @@ // //--------------------------------------------------------------------- +using Microsoft.OData.Edm.Vocabularies; using System.Collections.Generic; namespace Microsoft.OData.Edm @@ -23,4 +24,11 @@ public interface IEdmPathExpression : IEdmExpression /// string Path { get; } } + + + + [System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1040:Avoid empty interfaces", Justification = "marker interface")] + public interface IEdmNavigationPropertyPath : IEdmPathExpression, IEdmVocabularyAnnotatable + { + } } diff --git a/src/Microsoft.OData.Edm/Vocabularies/Expressions/EdmNavigationPropertyPathExpression.cs b/src/Microsoft.OData.Edm/Vocabularies/Expressions/EdmNavigationPropertyPathExpression.cs index 798d9eec01..d543879d52 100644 --- a/src/Microsoft.OData.Edm/Vocabularies/Expressions/EdmNavigationPropertyPathExpression.cs +++ b/src/Microsoft.OData.Edm/Vocabularies/Expressions/EdmNavigationPropertyPathExpression.cs @@ -11,7 +11,7 @@ namespace Microsoft.OData.Edm.Vocabularies /// /// Represents an EDM navigation property path expression. /// - public class EdmNavigationPropertyPathExpression : EdmPathExpression + public class EdmNavigationPropertyPathExpression : EdmPathExpression, IEdmNavigationPropertyPath { /// /// Initializes a new instance of the class. diff --git a/test/FunctionalTests/Microsoft.OData.Edm.Tests/Csdl/CsdlWriterTests.cs b/test/FunctionalTests/Microsoft.OData.Edm.Tests/Csdl/CsdlWriterTests.cs index edd09a85aa..48ca973595 100644 --- a/test/FunctionalTests/Microsoft.OData.Edm.Tests/Csdl/CsdlWriterTests.cs +++ b/test/FunctionalTests/Microsoft.OData.Edm.Tests/Csdl/CsdlWriterTests.cs @@ -2441,6 +2441,44 @@ public void ValidateEdmxVersions(string odataVersion) WriteAndVerifyJson(edmModel, "{\"$Version\":\"" + odataVersion + "\"}", false); } + + [Fact] + public void CanWriteNavigationPropertyPathAnnotation() + { + EdmModel model = new EdmModel(); + const string schemaNamespace = "example.org"; + var entity01= new EdmEntityType(schemaNamespace, "entity01"); + entity01.AddKeys(entity01.AddStructuralProperty("key", EdmPrimitiveTypeKind.String)); + model.AddElement(entity01); + + var entity02 = new EdmEntityType(schemaNamespace, "entity02"); + entity02.AddKeys(entity02.AddStructuralProperty("key", EdmPrimitiveTypeKind.String)); + entity02.AddUnidirectionalNavigation(new EdmNavigationPropertyInfo {Name = "other", Target = entity01, TargetMultiplicity=EdmMultiplicity.Many }); + model.AddElement(entity02); + + // Act & Assert for XML + WriteAndVerifyXml(model, @"" + + @"" + + @""+ + @"" + + @"" + + @"" + + @"" + + @"" + + @"" + + @"" + + @"" + + @"" + + @"" + + @"" + + @"" + + @"" + + @"" + + @"" + + @"" + + @""); + } + private void WriteAndVerifyXml(IEdmModel model, string expected, CsdlTarget target = CsdlTarget.OData) { using (StringWriter sw = new StringWriter()) diff --git a/test/FunctionalTests/Microsoft.OData.Edm.Tests/EdmUtilTests.cs b/test/FunctionalTests/Microsoft.OData.Edm.Tests/EdmUtilTests.cs index dc9c7777fc..caafde50b7 100644 --- a/test/FunctionalTests/Microsoft.OData.Edm.Tests/EdmUtilTests.cs +++ b/test/FunctionalTests/Microsoft.OData.Edm.Tests/EdmUtilTests.cs @@ -29,6 +29,17 @@ public void EntitySetShouldProduceCorrectFullyQualifiedName() Assert.Equal("d.s.container/entitySet", EdmUtil.FullyQualifiedName(entitySet)); } + [Fact] + public void EdmNavigationPropertyHasAnnotationTargetName() + { + // arrange + var path = new Edm.Vocabularies.EdmNavigationPropertyPathExpression("foo/bar/baz"); + // act + var actual = EdmUtil.FullyQualifiedName(path); + // assert + Assert.Equal("foo/bar/baz", actual); + } + [Theory] [InlineData("", false)] [InlineData(" ", false)] From f48c61a0dd500425f09000f3391a39e0204752fd Mon Sep 17 00:00:00 2001 From: Christof Sprenger Date: Wed, 3 Nov 2021 18:00:57 -0700 Subject: [PATCH 2/2] failing test --- .../Microsoft.OData.Edm.Tests/Csdl/CsdlWriterTests.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/FunctionalTests/Microsoft.OData.Edm.Tests/Csdl/CsdlWriterTests.cs b/test/FunctionalTests/Microsoft.OData.Edm.Tests/Csdl/CsdlWriterTests.cs index 48ca973595..31d37def8e 100644 --- a/test/FunctionalTests/Microsoft.OData.Edm.Tests/Csdl/CsdlWriterTests.cs +++ b/test/FunctionalTests/Microsoft.OData.Edm.Tests/Csdl/CsdlWriterTests.cs @@ -2456,6 +2456,9 @@ public void CanWriteNavigationPropertyPathAnnotation() entity02.AddUnidirectionalNavigation(new EdmNavigationPropertyInfo {Name = "other", Target = entity01, TargetMultiplicity=EdmMultiplicity.Many }); model.AddElement(entity02); + var annotation = new EdmVocabularyAnnotation(new EdmNavigationPropertyPathExpression("foo/bar"), CoreVocabularyModel.DescriptionTerm, new EdmStringConstant("test")); + model.AddVocabularyAnnotation(annotation); + // Act & Assert for XML WriteAndVerifyXml(model, @"" + @"" +