1+ using System ;
12using System . Collections . Generic ;
3+ using System . Linq ;
24using System . Threading . Tasks ;
35using JsonApiDotNetCore . Builders ;
46using JsonApiDotNetCore . Internal ;
810
911namespace JsonApiDotNetCore . Services . Operations . Processors
1012{
13+ /// <summary>
14+ /// Handles all "<see cref="OperationCode.get"/>" operations
15+ /// </summary>
16+ /// <typeparam name="T">The resource type</typeparam>
1117 public interface IGetOpProcessor < T > : IOpProcessor
1218 where T : class , IIdentifiable < int >
1319 { }
1420
21+ /// <summary>
22+ /// Handles all "<see cref="OperationCode.get"/>" operations
23+ /// </summary>
24+ /// <typeparam name="T">The resource type</typeparam>
25+ /// <typeparam name="TId">The resource identifier type</typeparam>
1526 public interface IGetOpProcessor < T , TId > : IOpProcessor
1627 where T : class , IIdentifiable < TId >
1728 { }
1829
30+ /// <inheritdoc />
1931 public class GetOpProcessor < T > : GetOpProcessor < T , int >
2032 where T : class , IIdentifiable < int >
2133 {
34+ /// <inheritdoc />
2235 public GetOpProcessor (
2336 IGetAllService < T , int > getAll ,
2437 IGetByIdService < T , int > getById ,
38+ IGetRelationshipService < T , int > getRelationship ,
2539 IJsonApiDeSerializer deSerializer ,
2640 IDocumentBuilder documentBuilder ,
2741 IContextGraph contextGraph ,
2842 IJsonApiContext jsonApiContext
29- ) : base ( getAll , getById , deSerializer , documentBuilder , contextGraph , jsonApiContext )
43+ ) : base ( getAll , getById , getRelationship , deSerializer , documentBuilder , contextGraph , jsonApiContext )
3044 { }
3145 }
3246
47+ /// <inheritdoc />
3348 public class GetOpProcessor < T , TId > : IGetOpProcessor < T , TId >
3449 where T : class , IIdentifiable < TId >
3550 {
3651 private readonly IGetAllService < T , TId > _getAll ;
3752 private readonly IGetByIdService < T , TId > _getById ;
53+ private readonly IGetRelationshipService < T , TId > _getRelationship ;
3854 private readonly IJsonApiDeSerializer _deSerializer ;
3955 private readonly IDocumentBuilder _documentBuilder ;
4056 private readonly IContextGraph _contextGraph ;
4157 private readonly IJsonApiContext _jsonApiContext ;
4258
59+ /// <inheritdoc />
4360 public GetOpProcessor (
4461 IGetAllService < T , TId > getAll ,
4562 IGetByIdService < T , TId > getById ,
63+ IGetRelationshipService < T , TId > getRelationship ,
4664 IJsonApiDeSerializer deSerializer ,
4765 IDocumentBuilder documentBuilder ,
4866 IContextGraph contextGraph ,
4967 IJsonApiContext jsonApiContext )
5068 {
5169 _getAll = getAll ;
5270 _getById = getById ;
71+ _getRelationship = getRelationship ;
5372 _deSerializer = deSerializer ;
5473 _documentBuilder = documentBuilder ;
5574 _contextGraph = contextGraph ;
5675 _jsonApiContext = jsonApiContext . ApplyContext < T > ( this ) ;
5776 }
5877
78+ /// <inheritdoc />
5979 public async Task < Operation > ProcessAsync ( Operation operation )
6080 {
6181 var operationResult = new Operation
6282 {
6383 Op = OperationCode . get
6484 } ;
6585
66- operationResult . Data = string . IsNullOrWhiteSpace ( operation . Ref . Id ? . ToString ( ) )
86+ operationResult . Data = string . IsNullOrWhiteSpace ( operation . Ref . Id )
6787 ? await GetAllAsync ( operation )
68- : await GetByIdAsync ( operation ) ;
88+ : string . IsNullOrWhiteSpace ( operation . Ref . Relationship )
89+ ? await GetByIdAsync ( operation )
90+ : await GetRelationshipAsync ( operation ) ;
6991
7092 return operationResult ;
7193 }
@@ -88,7 +110,7 @@ private async Task<object> GetAllAsync(Operation operation)
88110
89111 private async Task < object > GetByIdAsync ( Operation operation )
90112 {
91- var id = TypeHelper . ConvertType < TId > ( operation . Ref . Id ) ;
113+ var id = GetReferenceId ( operation ) ;
92114 var result = await _getById . GetAsync ( id ) ;
93115
94116 // this is a bit ugly but we need to bomb the entire transaction if the entity cannot be found
@@ -104,5 +126,23 @@ private async Task<object> GetByIdAsync(Operation operation)
104126
105127 return doc ;
106128 }
129+
130+ private async Task < object > GetRelationshipAsync ( Operation operation )
131+ {
132+ var id = GetReferenceId ( operation ) ;
133+ var result = await _getRelationship . GetRelationshipAsync ( id , operation . Ref . Relationship ) ;
134+
135+ // TODO: need a better way to get the ContextEntity from a relationship name
136+ // when no generic parameter is available
137+ var relationshipType = _contextGraph . GetContextEntity ( operation . GetResourceTypeName ( ) )
138+ . Relationships . Single ( r => r . Is ( operation . Ref . Relationship ) ) . Type ;
139+ var relatedContextEntity = _jsonApiContext . ContextGraph . GetContextEntity ( relationshipType ) ;
140+
141+ var doc = _documentBuilder . GetData ( relatedContextEntity , result as IIdentifiable ) ; // TODO: if this is safe, then it should be cast in the GetRelationshipAsync call
142+
143+ return doc ;
144+ }
145+
146+ private TId GetReferenceId ( Operation operation ) => TypeHelper . ConvertType < TId > ( operation . Ref . Id ) ;
107147 }
108148}
0 commit comments