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 176b200dc1..8318333048 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 c5849053c1..4444446937 100644
--- a/test/FunctionalTests/Microsoft.OData.Edm.Tests/Csdl/CsdlWriterTests.cs
+++ b/test/FunctionalTests/Microsoft.OData.Edm.Tests/Csdl/CsdlWriterTests.cs
@@ -2685,6 +2685,47 @@ 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);
+
+ var annotation = new EdmVocabularyAnnotation(new EdmNavigationPropertyPathExpression("foo/bar"), CoreVocabularyModel.DescriptionTerm, new EdmStringConstant("test"));
+ model.AddVocabularyAnnotation(annotation);
+
+ // Act & Assert for XML
+ WriteAndVerifyXml(model, @"" +
+ @"" +
+ @"" +
+ @"" +
+ @"" +
+ @"" +
+ @"" +
+ @"" +
+ @"" +
+ @"" +
+ @"" +
+ @"" +
+ @"" +
+ @"" +
+ @"" +
+ @"" +
+ @"" +
+ @"" +
+ @"" +
+ @"");
+ }
+
internal static 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)]