Skip to content

Commit 61372ff

Browse files
committed
implement new resource definition featurees
1 parent 38c39a0 commit 61372ff

File tree

4 files changed

+66
-15
lines changed

4 files changed

+66
-15
lines changed

src/JsonApiDotNetCore/Data/DefaultEntityRepository.cs

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,17 @@ public class DefaultEntityRepository<TEntity>
2121
{
2222
public DefaultEntityRepository(
2323
IJsonApiContext jsonApiContext,
24-
IDbContextResolver contextResolver)
25-
: base(jsonApiContext, contextResolver)
24+
IDbContextResolver contextResolver,
25+
ResourceDefinition<TEntity> resourceDefinition = null)
26+
: base(jsonApiContext, contextResolver, resourceDefinition)
2627
{ }
2728

2829
public DefaultEntityRepository(
2930
ILoggerFactory loggerFactory,
3031
IJsonApiContext jsonApiContext,
31-
IDbContextResolver contextResolver)
32-
: base(loggerFactory, jsonApiContext, contextResolver)
32+
IDbContextResolver contextResolver,
33+
ResourceDefinition<TEntity> resourceDefinition = null)
34+
: base(loggerFactory, jsonApiContext, contextResolver, resourceDefinition)
3335
{ }
3436
}
3537

@@ -47,27 +49,32 @@ public class DefaultEntityRepository<TEntity, TId>
4749
private readonly ILogger _logger;
4850
private readonly IJsonApiContext _jsonApiContext;
4951
private readonly IGenericProcessorFactory _genericProcessorFactory;
52+
private readonly ResourceDefinition<TEntity> _resourceDefinition;
5053

5154
public DefaultEntityRepository(
5255
IJsonApiContext jsonApiContext,
53-
IDbContextResolver contextResolver)
56+
IDbContextResolver contextResolver,
57+
ResourceDefinition<TEntity> resourceDefinition = null)
5458
{
5559
_context = contextResolver.GetContext();
5660
_dbSet = contextResolver.GetDbSet<TEntity>();
5761
_jsonApiContext = jsonApiContext;
5862
_genericProcessorFactory = _jsonApiContext.GenericProcessorFactory;
63+
_resourceDefinition = resourceDefinition;
5964
}
6065

6166
public DefaultEntityRepository(
6267
ILoggerFactory loggerFactory,
6368
IJsonApiContext jsonApiContext,
64-
IDbContextResolver contextResolver)
69+
IDbContextResolver contextResolver,
70+
ResourceDefinition<TEntity> resourceDefinition = null)
6571
{
6672
_context = contextResolver.GetContext();
6773
_dbSet = contextResolver.GetDbSet<TEntity>();
6874
_jsonApiContext = jsonApiContext;
6975
_logger = loggerFactory.CreateLogger<DefaultEntityRepository<TEntity, TId>>();
7076
_genericProcessorFactory = _jsonApiContext.GenericProcessorFactory;
77+
_resourceDefinition = resourceDefinition;
7178
}
7279

7380
/// <inheritdoc />
@@ -82,13 +89,38 @@ public virtual IQueryable<TEntity> Get()
8289
/// <inheritdoc />
8390
public virtual IQueryable<TEntity> Filter(IQueryable<TEntity> entities, FilterQuery filterQuery)
8491
{
92+
if(_resourceDefinition != null)
93+
{
94+
var defaultQueryFilters = _resourceDefinition.GetQueryFilters();
95+
if(defaultQueryFilters != null && defaultQueryFilters.TryGetValue(filterQuery.Attribute, out var defaultQueryFilter) == true)
96+
{
97+
return defaultQueryFilter(entities, filterQuery.Value);
98+
}
99+
}
100+
85101
return entities.Filter(_jsonApiContext, filterQuery);
86102
}
87103

88104
/// <inheritdoc />
89105
public virtual IQueryable<TEntity> Sort(IQueryable<TEntity> entities, List<SortQuery> sortQueries)
90106
{
91-
return entities.Sort(sortQueries);
107+
if (sortQueries != null && sortQueries.Count > 0)
108+
return entities.Sort(sortQueries);
109+
110+
if(_resourceDefinition != null)
111+
{
112+
var defaultSortOrder = _resourceDefinition.DefaultSort();
113+
if(defaultSortOrder != null && defaultSortOrder.Count > 0)
114+
{
115+
foreach(var sortProp in defaultSortOrder)
116+
{
117+
// this is dumb...add an overload, don't allocate for no reason
118+
entities.Sort(new SortQuery(sortProp.Item2, sortProp.Item1));
119+
}
120+
}
121+
}
122+
123+
return entities;
92124
}
93125

94126
/// <inheritdoc />

src/JsonApiDotNetCore/Models/ResourceDefinition.cs

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,10 @@ private bool InstanceOutputAttrsAreSpecified()
4949
.FirstOrDefault();
5050
var declaringType = instanceMethod?.DeclaringType;
5151
return declaringType == derivedType;
52-
}
53-
54-
public delegate dynamic FilterExpression(T type);
52+
}
5553

5654
// TODO: need to investigate options for caching these
57-
protected List<AttrAttribute> Remove(Expression<FilterExpression> filter, List<AttrAttribute> from = null)
55+
protected List<AttrAttribute> Remove(Expression<Func<T, dynamic>> filter, List<AttrAttribute> from = null)
5856
{
5957
from = from ?? _contextEntity.Attributes;
6058

@@ -155,7 +153,7 @@ private List<AttrAttribute> GetOutputAttrs()
155153
/// }
156154
/// </code>
157155
/// </example>
158-
protected virtual QueryFilters GetQueryFilters() => null;
156+
public virtual QueryFilters GetQueryFilters() => null;
159157

160158
/// <summary>
161159
/// This is an alias type intended to simplify the implementation's
@@ -181,6 +179,28 @@ public class QueryFilters : Dictionary<string, Func<IQueryable<T>, string, IQuer
181179
/// </example>
182180
protected virtual PropertySortOrder GetDefaultSortOrder() => null;
183181

182+
internal List<(AttrAttribute, SortDirection)> DefaultSort()
183+
{
184+
var defaultSortOrder = GetDefaultSortOrder();
185+
if(defaultSortOrder != null && defaultSortOrder.Count > 0)
186+
{
187+
var order = new List<(AttrAttribute, SortDirection)>();
188+
foreach(var sortProp in defaultSortOrder)
189+
{
190+
// TODO: error handling, log or throw?
191+
if (sortProp.Item1.Body is MemberExpression memberExpression)
192+
order.Add(
193+
(_contextEntity.Attributes.SingleOrDefault(a => a.InternalAttributeName != memberExpression.Member.Name),
194+
sortProp.Item2)
195+
);
196+
}
197+
198+
return order;
199+
}
200+
201+
return null;
202+
}
203+
184204
/// <summary>
185205
/// This is an alias type intended to simplify the implementation's
186206
/// method signature.

src/JsonApiDotNetCore/Services/EntityResourceService.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -223,8 +223,7 @@ protected virtual IQueryable<TEntity> ApplySortAndFilterQuery(IQueryable<TEntity
223223
foreach (var filter in query.Filters)
224224
entities = _entities.Filter(entities, filter);
225225

226-
if (query.SortParameters != null && query.SortParameters.Count > 0)
227-
entities = _entities.Sort(entities, query.SortParameters);
226+
entities = _entities.Sort(entities, query.SortParameters);
228227

229228
return entities;
230229
}

test/UnitTests/Models/ResourceDefinitionTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ protected override List<AttrAttribute> OutputAttrs()
120120
? Remove(m => m.AlwaysExcluded)
121121
: Remove(m => new { m.AlwaysExcluded, m.Password }, from: base.OutputAttrs());
122122

123-
protected override QueryFilters GetQueryFilters()
123+
public override QueryFilters GetQueryFilters()
124124
=> new QueryFilters {
125125
{ "is-active", (query, value) => query.Select(x => x) }
126126
};

0 commit comments

Comments
 (0)