@@ -19,82 +19,112 @@ namespace Microsoft.OpenApi.OData.Generator
19
19
internal static class OpenApiLinkGenerator
20
20
{
21
21
/// <summary>
22
- /// Create the collection of <see cref="OpenApiLink"/> object.
22
+ /// Create the collection of <see cref="OpenApiLink"/> object for an entity or collection of entities .
23
23
/// </summary>
24
24
/// <param name="context">The OData context.</param>
25
25
/// <param name="entityType">The Entity type.</param>
26
26
/// <param name ="entityName">The name of the source of the <see cref="IEdmEntityType"/> object.</param>
27
27
/// <param name="entityKind">"The kind of the source of the <see cref="IEdmEntityType"/> object.</param>
28
- /// <param name="parameters">"The list of parameters of the incoming operation.</param>
29
- /// <param name="navPropOperationId">Optional parameter: The operation id of the source of the NavigationProperty object.</param>
28
+ /// <param name="path">The OData path of the operation the links are to be generated for.</param>
29
+ /// <param name="parameters">"Optional: The list of parameters of the incoming operation.</param>
30
+ /// <param name="navPropOperationId">Optional: The operation id of the source of the NavigationProperty object.</param>
30
31
/// <returns>The created dictionary of <see cref="OpenApiLink"/> object.</returns>
31
32
public static IDictionary < string , OpenApiLink > CreateLinks ( this ODataContext context ,
32
- IEdmEntityType entityType , string entityName , string entityKind ,
33
- IList < OpenApiParameter > parameters , string navPropOperationId = null )
33
+ IEdmEntityType entityType , string entityName , string entityKind , ODataPath path ,
34
+ IList < OpenApiParameter > parameters = null , string navPropOperationId = null )
34
35
{
35
- IDictionary < string , OpenApiLink > links = new Dictionary < string , OpenApiLink > ( ) ;
36
-
37
36
Utils . CheckArgumentNull ( context , nameof ( context ) ) ;
38
37
Utils . CheckArgumentNull ( entityType , nameof ( entityType ) ) ;
39
38
Utils . CheckArgumentNullOrEmpty ( entityName , nameof ( entityName ) ) ;
40
39
Utils . CheckArgumentNullOrEmpty ( entityKind , nameof ( entityKind ) ) ;
41
- Utils . CheckArgumentNull ( parameters , nameof ( parameters ) ) ;
40
+ Utils . CheckArgumentNull ( path , nameof ( path ) ) ;
42
41
43
- List < string > pathKeyNames = new List < string > ( ) ;
42
+ List < string > pathKeyNames = new ( ) ;
44
43
45
44
// Fetch defined Id(s) from incoming parameters (if any)
46
- foreach ( var parameter in parameters )
45
+ if ( parameters != null )
47
46
{
48
- if ( ! string . IsNullOrEmpty ( parameter . Description ) &&
49
- parameter . Description . ToLower ( ) . Contains ( "key" ) )
47
+ foreach ( var parameter in parameters )
50
48
{
51
- pathKeyNames . Add ( parameter . Name ) ;
49
+ if ( ! string . IsNullOrEmpty ( parameter . Description ) &&
50
+ parameter . Description . ToLower ( ) . Contains ( "key" ) )
51
+ {
52
+ pathKeyNames . Add ( parameter . Name ) ;
53
+ }
52
54
}
53
55
}
54
56
55
- foreach ( IEdmNavigationProperty navProp in entityType . NavigationProperties ( ) )
56
- {
57
- string navPropName = navProp . Name ;
58
- string operationId ;
59
- string operationPrefix ;
57
+ Dictionary < string , OpenApiLink > links = new ( ) ;
58
+ bool lastSegmentIsColNavProp = ( path . LastSegment as ODataNavigationPropertySegment ) ? . NavigationProperty . TargetMultiplicity ( ) == EdmMultiplicity . Many ;
60
59
61
- switch ( entityKind )
60
+ // Valid only for non collection-valued navigation properties
61
+ if ( ! lastSegmentIsColNavProp )
62
+ {
63
+ foreach ( IEdmNavigationProperty navProp in entityType . NavigationProperties ( ) )
62
64
{
63
- case "Navigation" : // just for contained navigations
64
- operationPrefix = navPropOperationId ;
65
- break ;
66
- default : // EntitySet, Entity, Singleton
67
- operationPrefix = entityName ;
68
- break ;
69
- }
65
+ string navPropName = navProp . Name ;
66
+ string operationId ;
67
+ string operationPrefix ;
70
68
71
- if ( navProp . TargetMultiplicity ( ) == EdmMultiplicity . Many )
72
- {
73
- operationId = operationPrefix + ".List" + Utils . UpperFirstChar ( navPropName ) ;
74
- }
75
- else
76
- {
77
- operationId = operationPrefix + ".Get" + Utils . UpperFirstChar ( navPropName ) ;
78
- }
69
+ switch ( entityKind )
70
+ {
71
+ case "Navigation" : // just for contained navigations
72
+ operationPrefix = navPropOperationId ;
73
+ break ;
74
+ default : // EntitySet, Entity, Singleton
75
+ operationPrefix = entityName ;
76
+ break ;
77
+ }
79
78
80
- OpenApiLink link = new OpenApiLink
81
- {
82
- OperationId = operationId ,
83
- Parameters = new Dictionary < string , RuntimeExpressionAnyWrapper > ( )
84
- } ;
79
+ if ( navProp . TargetMultiplicity ( ) == EdmMultiplicity . Many )
80
+ {
81
+ operationId = operationPrefix + ".List" + Utils . UpperFirstChar ( navPropName ) ;
82
+ }
83
+ else
84
+ {
85
+ operationId = operationPrefix + ".Get" + Utils . UpperFirstChar ( navPropName ) ;
86
+ }
85
87
86
- if ( pathKeyNames . Any ( ) )
87
- {
88
- foreach ( var pathKeyName in pathKeyNames )
88
+ OpenApiLink link = new OpenApiLink
89
89
{
90
- link . Parameters [ pathKeyName ] = new RuntimeExpressionAnyWrapper
90
+ OperationId = operationId ,
91
+ Parameters = new Dictionary < string , RuntimeExpressionAnyWrapper > ( )
92
+ } ;
93
+
94
+ if ( pathKeyNames . Any ( ) )
95
+ {
96
+ foreach ( var pathKeyName in pathKeyNames )
91
97
{
92
- Any = new OpenApiString ( "$request.path." + pathKeyName )
93
- } ;
98
+ link . Parameters [ pathKeyName ] = new RuntimeExpressionAnyWrapper
99
+ {
100
+ Any = new OpenApiString ( "$request.path." + pathKeyName )
101
+ } ;
102
+ }
94
103
}
104
+
105
+ links [ navProp . Name ] = link ;
95
106
}
107
+ }
96
108
97
- links [ navProp . Name ] = link ;
109
+ // Get the Operations and OperationImport paths bound to this (collection of) entity.
110
+ IEnumerable < ODataPath > operationPaths = context . AllPaths . Where ( p => ( p . Kind . Equals ( ODataPathKind . Operation ) || p . Kind . Equals ( ODataPathKind . OperationImport ) ) &&
111
+ path . GetPathItemName ( ) . Equals ( p . Clone ( ) . Pop ( ) . GetPathItemName ( ) ) ) ;
112
+
113
+ // Generate links to the Operations and OperationImport operations.
114
+ if ( operationPaths . Any ( ) )
115
+ {
116
+ foreach ( var operationPath in operationPaths )
117
+ {
118
+ OpenApiLink link = new ( )
119
+ {
120
+ OperationId = string . Join ( "." , operationPath . Segments . Select ( x =>
121
+ {
122
+ return x . Kind . Equals ( ODataSegmentKind . Key ) ? x . EntityType . Name : x . Identifier ;
123
+ } ) )
124
+ } ;
125
+
126
+ links [ operationPath . LastSegment . Identifier ] = link ;
127
+ }
98
128
}
99
129
100
130
return links ;
0 commit comments