This repository was archived by the owner on Jun 17, 2025. It is now read-only.
forked from JSONAPIdotNET/JSONAPI.NET
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMappedDocumentMaterializer.cs
More file actions
123 lines (108 loc) · 5.58 KB
/
Copy pathMappedDocumentMaterializer.cs
File metadata and controls
123 lines (108 loc) · 5.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Net.Http;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using JSONAPI.Core;
using JSONAPI.Documents;
using JSONAPI.Documents.Builders;
using JSONAPI.QueryableTransformers;
namespace JSONAPI.Http
{
/// <summary>
/// Document materializer for mapping from a database entity to a data transfer object.
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <typeparam name="TDto"></typeparam>
public abstract class MappedDocumentMaterializer<TEntity, TDto> : IDocumentMaterializer where TDto : class
{
private readonly IQueryableResourceCollectionDocumentBuilder _queryableResourceCollectionDocumentBuilder;
private readonly IBaseUrlService _baseUrlService;
private readonly ISingleResourceDocumentBuilder _singleResourceDocumentBuilder;
private readonly IQueryableEnumerationTransformer _queryableEnumerationTransformer;
private readonly IResourceTypeRegistry _resourceTypeRegistry;
/// <summary>
/// Gets a query returning all entities for this endpoint
/// </summary>
protected abstract IQueryable<TEntity> GetQuery();
/// <summary>
/// Gets a query for only the entity matching the given ID
/// </summary>
protected abstract IQueryable<TEntity> GetByIdQuery(string id);
/// <summary>
/// Gets a query for the DTOs based on the given entity query.
/// </summary>
protected abstract IQueryable<TDto> GetMappedQuery(IQueryable<TEntity> entityQuery, Expression<Func<TDto, object>>[] propertiesToInclude);
/// <summary>
/// Creates a new MappedDocumentMaterializer
/// </summary>
protected MappedDocumentMaterializer(
IQueryableResourceCollectionDocumentBuilder queryableResourceCollectionDocumentBuilder,
IBaseUrlService baseUrlService,
ISingleResourceDocumentBuilder singleResourceDocumentBuilder,
IQueryableEnumerationTransformer queryableEnumerationTransformer,
IResourceTypeRegistry resourceTypeRegistry)
{
_queryableResourceCollectionDocumentBuilder = queryableResourceCollectionDocumentBuilder;
_baseUrlService = baseUrlService;
_singleResourceDocumentBuilder = singleResourceDocumentBuilder;
_queryableEnumerationTransformer = queryableEnumerationTransformer;
_resourceTypeRegistry = resourceTypeRegistry;
}
private string ResourceTypeName
{
get { return _resourceTypeRegistry.GetRegistrationForType(typeof (TDto)).ResourceTypeName; }
}
public virtual async Task<IResourceCollectionDocument> GetRecords(HttpRequestMessage request, CancellationToken cancellationToken)
{
var entityQuery = GetQuery();
var includePaths = GetIncludePathsForQuery() ?? new Expression<Func<TDto, object>>[] { };
var jsonApiPaths = includePaths.Select(ConvertToJsonKeyPath).ToArray();
var mappedQuery = GetMappedQuery(entityQuery, includePaths);
return await _queryableResourceCollectionDocumentBuilder.BuildDocument(mappedQuery, request, cancellationToken, jsonApiPaths);
}
public virtual async Task<ISingleResourceDocument> GetRecordById(string id, HttpRequestMessage request, CancellationToken cancellationToken)
{
var entityQuery = GetByIdQuery(id);
var includePaths = GetIncludePathsForSingleResource() ?? new Expression<Func<TDto, object>>[] { };
var jsonApiPaths = includePaths.Select(ConvertToJsonKeyPath).ToArray();
var mappedQuery = GetMappedQuery(entityQuery, includePaths);
var primaryResource = await _queryableEnumerationTransformer.FirstOrDefault(mappedQuery, cancellationToken);
if (primaryResource == null)
throw JsonApiException.CreateForNotFound(
string.Format("No record exists with type `{0}` and ID `{1}`.", ResourceTypeName, id));
var baseUrl = _baseUrlService.GetBaseUrl(request);
return _singleResourceDocumentBuilder.BuildDocument(primaryResource, baseUrl, jsonApiPaths, null);
}
public abstract Task<ISingleResourceDocument> CreateRecord(ISingleResourceDocument requestDocument,
HttpRequestMessage request,
CancellationToken cancellationToken);
public abstract Task<ISingleResourceDocument> UpdateRecord(string id, ISingleResourceDocument requestDocument,
HttpRequestMessage request,
CancellationToken cancellationToken);
public abstract Task<IJsonApiDocument> DeleteRecord(string id, CancellationToken cancellationToken);
/// <summary>
/// Returns a list of property paths to be included when constructing a query for this resource type
/// </summary>
protected virtual Expression<Func<TDto, object>>[] GetIncludePathsForQuery()
{
return null;
}
/// <summary>
/// Returns a list of property paths to be included when returning a single resource of this resource type
/// </summary>
protected virtual Expression<Func<TDto, object>>[] GetIncludePathsForSingleResource()
{
return null;
}
private string ConvertToJsonKeyPath(Expression<Func<TDto, object>> expression)
{
var visitor = new PathVisitor(_resourceTypeRegistry);
visitor.Visit(expression);
return visitor.Path;
}
}
}