77using  System . Collections . Generic ; 
88using  System . Linq ; 
99using  Microsoft . OData . Edm ; 
10+ using  Microsoft . OpenApi . Any ; 
1011using  Microsoft . OpenApi . Models ; 
1112using  Microsoft . OpenApi . OData . Common ; 
1213using  Microsoft . OpenApi . OData . Edm ; 
1314using  Microsoft . OpenApi . OData . Generator ; 
15+ using  Microsoft . OpenApi . OData . Vocabulary . Capabilities ; 
1416
1517namespace  Microsoft . OpenApi . OData . Operation ; 
1618
@@ -28,6 +30,8 @@ internal class ODataTypeCastGetOperationHandler : OperationHandler
2830	/// </summary> 
2931	internal  ODataSegment  LastSecondSegment  {  get ;  set ;  } 
3032
33+ 	private  NavigationPropertyRestriction  restriction ; 
34+ 	private  IEdmNavigationProperty  navigationProperty ; 
3135	private  IEdmEntityType  parentEntityType ; 
3236	private  IEdmEntityType  targetEntityType ; 
3337	private  const  int  SecondLastSegmentIndex  =  2 ; 
@@ -42,6 +46,30 @@ protected override void Initialize(ODataContext context, ODataPath path)
4246			LastSecondSegment  =  path . Segments . ElementAt ( count  -  SecondLastSegmentIndex ) ; 
4347
4448		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 
4573		if ( path . Last ( )  is  ODataTypeCastSegment  oDataTypeCastSegment ) 
4674		{ 
4775			targetEntityType  =  oDataTypeCastSegment . EntityType ; 
@@ -140,7 +168,130 @@ protected override void SetResponses(OpenApiOperation operation)
140168
141169		base . SetResponses ( operation ) ; 
142170	} 
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