7
7
using System . Collections . Generic ;
8
8
using System . Linq ;
9
9
using Microsoft . OData . Edm ;
10
+ using Microsoft . OpenApi . Any ;
10
11
using Microsoft . OpenApi . Models ;
11
12
using Microsoft . OpenApi . OData . Common ;
12
13
using Microsoft . OpenApi . OData . Edm ;
13
14
using Microsoft . OpenApi . OData . Generator ;
15
+ using Microsoft . OpenApi . OData . Vocabulary . Capabilities ;
14
16
15
17
namespace Microsoft . OpenApi . OData . Operation ;
16
18
@@ -28,6 +30,8 @@ internal class ODataTypeCastGetOperationHandler : OperationHandler
28
30
/// </summary>
29
31
internal ODataSegment LastSecondSegment { get ; set ; }
30
32
33
+ private NavigationPropertyRestriction restriction ;
34
+ private IEdmNavigationProperty navigationProperty ;
31
35
private IEdmEntityType parentEntityType ;
32
36
private IEdmEntityType targetEntityType ;
33
37
private const int SecondLastSegmentIndex = 2 ;
@@ -42,6 +46,30 @@ protected override void Initialize(ODataContext context, ODataPath path)
42
46
LastSecondSegment = path . Segments . ElementAt ( count - SecondLastSegmentIndex ) ;
43
47
44
48
parentEntityType = LastSecondSegment . EntityType ;
49
+ if ( LastSecondSegment is ODataNavigationPropertySegment navigationPropertySegment )
50
+ {
51
+ navigationProperty = navigationPropertySegment . NavigationProperty ;
52
+ var navigationPropertyPath = string . Join ( "/" ,
53
+ Path . Segments . Where ( s => ! ( s is ODataKeySegment || s is ODataNavigationSourceSegment
54
+ || s is ODataStreamContentSegment || s is ODataStreamPropertySegment ) ) . Select ( e => e . Identifier ) ) ;
55
+
56
+ if ( path . FirstSegment is ODataNavigationSourceSegment navigationSourceSegment )
57
+ {
58
+ NavigationRestrictionsType navigation = navigationSourceSegment . NavigationSource switch {
59
+ IEdmEntitySet entitySet => Context . Model . GetRecord < NavigationRestrictionsType > ( entitySet , CapabilitiesConstants . NavigationRestrictions ) ,
60
+ IEdmSingleton singleton => Context . Model . GetRecord < NavigationRestrictionsType > ( singleton , CapabilitiesConstants . NavigationRestrictions ) ,
61
+ _ => null
62
+ } ;
63
+
64
+ if ( navigation ? . RestrictedProperties != null )
65
+ {
66
+ restriction = navigation . RestrictedProperties . FirstOrDefault ( r => r . NavigationProperty != null && r . NavigationProperty == navigationPropertyPath ) ;
67
+ }
68
+ }
69
+ }
70
+ //TODO previous segment is a key
71
+ //TODO previous segment is a single nav property
72
+ //TODO previous segment is an entity set
45
73
if ( path . Last ( ) is ODataTypeCastSegment oDataTypeCastSegment )
46
74
{
47
75
targetEntityType = oDataTypeCastSegment . EntityType ;
@@ -140,7 +168,130 @@ protected override void SetResponses(OpenApiOperation operation)
140
168
141
169
base . SetResponses ( operation ) ;
142
170
}
143
- //TODO query parameters?
144
- //TODO extensions?
145
- }
146
- //TODO unit tests
171
+ /// <inheritdoc/>
172
+ protected override void SetTags ( OpenApiOperation operation )
173
+ {
174
+ IList < string > items = new List < string >
175
+ {
176
+ parentEntityType . Name ,
177
+ targetEntityType . Name ,
178
+ } ;
179
+
180
+ string name = string . Join ( "." , items ) ;
181
+ OpenApiTag tag = new ( )
182
+ {
183
+ Name = name
184
+ } ;
185
+ tag . Extensions . Add ( Constants . xMsTocType , new OpenApiString ( "page" ) ) ;
186
+ operation . Tags . Add ( tag ) ;
187
+
188
+ Context . AppendTag ( tag ) ;
189
+
190
+ base . SetTags ( operation ) ;
191
+ }
192
+ /// <inheritdoc/>
193
+ protected override void SetParameters ( OpenApiOperation operation )
194
+ {
195
+ base . SetParameters ( operation ) ;
196
+
197
+ if ( navigationProperty != null ) {
198
+ if ( navigationProperty . TargetMultiplicity ( ) == EdmMultiplicity . Many )
199
+ {
200
+ // Need to verify that TopSupported or others should be applied to navigation source.
201
+ // So, how about for the navigation property.
202
+ OpenApiParameter parameter = Context . CreateTop ( navigationProperty ) ;
203
+ if ( parameter != null )
204
+ {
205
+ operation . Parameters . Add ( parameter ) ;
206
+ }
207
+
208
+ parameter = Context . CreateSkip ( navigationProperty ) ;
209
+ if ( parameter != null )
210
+ {
211
+ operation . Parameters . Add ( parameter ) ;
212
+ }
213
+
214
+ parameter = Context . CreateSearch ( navigationProperty ) ;
215
+ if ( parameter != null )
216
+ {
217
+ operation . Parameters . Add ( parameter ) ;
218
+ }
219
+
220
+ parameter = Context . CreateFilter ( navigationProperty ) ;
221
+ if ( parameter != null )
222
+ {
223
+ operation . Parameters . Add ( parameter ) ;
224
+ }
225
+
226
+ parameter = Context . CreateCount ( navigationProperty ) ;
227
+ if ( parameter != null )
228
+ {
229
+ operation . Parameters . Add ( parameter ) ;
230
+ }
231
+
232
+ parameter = Context . CreateOrderBy ( navigationProperty ) ;
233
+ if ( parameter != null )
234
+ {
235
+ operation . Parameters . Add ( parameter ) ;
236
+ }
237
+
238
+ parameter = Context . CreateSelect ( navigationProperty ) ;
239
+ if ( parameter != null )
240
+ {
241
+ operation . Parameters . Add ( parameter ) ;
242
+ }
243
+
244
+ parameter = Context . CreateExpand ( navigationProperty ) ;
245
+ if ( parameter != null )
246
+ {
247
+ operation . Parameters . Add ( parameter ) ;
248
+ }
249
+ }
250
+ else
251
+ {
252
+ OpenApiParameter parameter = Context . CreateSelect ( navigationProperty ) ;
253
+ if ( parameter != null )
254
+ {
255
+ operation . Parameters . Add ( parameter ) ;
256
+ }
257
+
258
+ parameter = Context . CreateExpand ( navigationProperty ) ;
259
+ if ( parameter != null )
260
+ {
261
+ operation . Parameters . Add ( parameter ) ;
262
+ }
263
+ }
264
+ }
265
+ }
266
+
267
+ protected override void SetSecurity ( OpenApiOperation operation )
268
+ {
269
+ if ( restriction == null || restriction . ReadRestrictions == null )
270
+ {
271
+ return ;
272
+ }
273
+
274
+ ReadRestrictionsBase readBase = restriction . ReadRestrictions ;
275
+
276
+ operation . Security = Context . CreateSecurityRequirements ( readBase . Permissions ) . ToList ( ) ;
277
+ }
278
+
279
+ protected override void SetExtensions ( OpenApiOperation operation )
280
+ {
281
+ if ( Context . Settings . EnablePagination )
282
+ {
283
+ if ( navigationProperty != null && navigationProperty . TargetMultiplicity ( ) == EdmMultiplicity . Many )
284
+ {
285
+ OpenApiObject extension = new ( )
286
+ {
287
+ { "nextLinkName" , new OpenApiString ( "@odata.nextLink" ) } ,
288
+ { "operationName" , new OpenApiString ( Context . Settings . PageableOperationName ) }
289
+ } ;
290
+
291
+ operation . Extensions . Add ( Constants . xMsPageable , extension ) ;
292
+ }
293
+ }
294
+
295
+ base . SetExtensions ( operation ) ;
296
+ }
297
+ }
0 commit comments