Skip to content

Commit

Permalink
TODO: Replace squashed changes from #1142 with rebase on master after…
Browse files Browse the repository at this point in the history
… merge

Removed existing resource inheritance tests

Resource inheritance: return derived types

Resource inheritance: sparse fieldsets

Changed the expression tokenizer to recognize dots in field chains

Resource inheritance: derived includes

Resource inheritance: derived filters

Added ResourceFieldAttribute.Type and use it from QueryExpression.ToFullString() to provide improved debug info

Resource inheritance: sorting on derived fields

Added missing tests for GET abstract/concrete base primary types at secondary/relationship endpoints

Resource graph validation: fail if field from base type does not exist on derived type

Clarified error message on type mismatch in request body

Rename inheritance tests

Added extension method to obtain ClrType of a resource instance (we'll need this later)

Resource inheritance: write endpoints

Updated documentation

Added rewriter unit tests to improve code coverage

Exclude example project from code coverage
  • Loading branch information
Bart Koelman committed Apr 1, 2022
1 parent 978a311 commit e8c146c
Show file tree
Hide file tree
Showing 188 changed files with 10,174 additions and 1,390 deletions.
18 changes: 13 additions & 5 deletions benchmarks/Serialization/ResourceSerializationBenchmarks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -127,11 +127,19 @@ protected override IEvaluatedIncludeCache CreateEvaluatedIncludeCache(IResourceG
RelationshipAttribute multi4 = resourceAType.GetRelationshipByPropertyName(nameof(OutgoingResource.Multi4));
RelationshipAttribute multi5 = resourceAType.GetRelationshipByPropertyName(nameof(OutgoingResource.Multi5));

ImmutableArray<ResourceFieldAttribute> chain = ImmutableArray.Create<ResourceFieldAttribute>(single2, single3, multi4, multi5);
IEnumerable<ResourceFieldChainExpression> chains = new ResourceFieldChainExpression(chain).AsEnumerable();

var converter = new IncludeChainConverter();
IncludeExpression include = converter.FromRelationshipChains(chains);
var include = new IncludeExpression(new HashSet<IncludeElementExpression>
{
new(single2, new HashSet<IncludeElementExpression>
{
new(single3, new HashSet<IncludeElementExpression>
{
new(multi4, new HashSet<IncludeElementExpression>
{
new(multi5)
}.ToImmutableHashSet())
}.ToImmutableHashSet())
}.ToImmutableHashSet())
}.ToImmutableHashSet());

var cache = new EvaluatedIncludeCache();
cache.Set(include);
Expand Down
4 changes: 2 additions & 2 deletions benchmarks/Serialization/SerializationBenchmarkBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -180,9 +180,9 @@ public Task OnSetToManyRelationshipAsync<TResource>(TResource leftResource, HasM
return Task.CompletedTask;
}

public Task OnAddToRelationshipAsync<TResource, TId>(TId leftResourceId, HasManyAttribute hasManyRelationship, ISet<IIdentifiable> rightResourceIds,
public Task OnAddToRelationshipAsync<TResource>(TResource leftResource, HasManyAttribute hasManyRelationship, ISet<IIdentifiable> rightResourceIds,
CancellationToken cancellationToken)
where TResource : class, IIdentifiable<TId>
where TResource : class, IIdentifiable
{
return Task.CompletedTask;
}
Expand Down
26 changes: 26 additions & 0 deletions docs/usage/reading/filtering.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ Expressions are composed using the following functions:
| Ends with text | `endsWith` | `?filter=endsWith(description,'End')` |
| Equals one value from set | `any` | `?filter=any(chapter,'Intro','Summary','Conclusion')` |
| Collection contains items | `has` | `?filter=has(articles)` |
| Type-check derived type (v5) | `isType` | `?filter=isType(,men)` |
| Negation | `not` | `?filter=not(equals(lastName,null))` |
| Conditional logical OR | `or` | `?filter=or(has(orders),has(invoices))` |
| Conditional logical AND | `and` | `?filter=and(has(orders),has(invoices))` |
Expand Down Expand Up @@ -86,6 +87,31 @@ GET /customers?filter=has(orders,not(equals(status,'Paid'))) HTTP/1.1

Which returns only customers that have at least one unpaid order.

_since v5.0_

Use the `isType` filter function to perform a type check on a derived type. You can pass a nested filter, where the derived fields are accessible.
The first parameter can be used to perform the type check on a to-one relationship path.

Only return men:
```http
GET /humans?filter=isType(,men) HTTP/1.1
```

Only return men with beards:
```http
GET /humans?filter=isType(,men,equals(hasBeard,'true')) HTTP/1.1
```

Only return people whose best friend is a man with children:
```http
GET /humans?filter=isType(bestFriend,men,has(children)) HTTP/1.1
```

Only return people who have at least one female married child:
```http
GET /humans?filter=has(children,isType(,woman,not(equals(husband,null)))) HTTP/1.1
```

# Legacy filters

The next section describes how filtering worked in versions prior to v4.0. They are always applied on the set of resources being requested (no nesting).
Expand Down
Loading

0 comments on commit e8c146c

Please sign in to comment.