Skip to content

Commit 7fcb58e

Browse files
author
Bart Koelman
committed
Use sets for include expressions
1 parent fbdcefb commit 7fcb58e

File tree

15 files changed

+47
-47
lines changed

15 files changed

+47
-47
lines changed

benchmarks/Serialization/SerializationBenchmarkBase.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ public sealed class ResourceA : Identifiable
130130

131131
private sealed class FakeResourceDefinitionAccessor : IResourceDefinitionAccessor
132132
{
133-
public IImmutableList<IncludeElementExpression> OnApplyIncludes(Type resourceType, IImmutableList<IncludeElementExpression> existingIncludes)
133+
public IImmutableSet<IncludeElementExpression> OnApplyIncludes(Type resourceType, IImmutableSet<IncludeElementExpression> existingIncludes)
134134
{
135135
return existingIncludes;
136136
}

src/JsonApiDotNetCore/Queries/Expressions/IncludeChainConverter.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,11 @@ public IncludeExpression FromRelationshipChains(IEnumerable<ResourceFieldChainEx
6868
{
6969
ArgumentGuard.NotNull(chains, nameof(chains));
7070

71-
IImmutableList<IncludeElementExpression> elements = ConvertChainsToElements(chains);
71+
IImmutableSet<IncludeElementExpression> elements = ConvertChainsToElements(chains);
7272
return elements.Any() ? new IncludeExpression(elements) : IncludeExpression.Empty;
7373
}
7474

75-
private static IImmutableList<IncludeElementExpression> ConvertChainsToElements(IEnumerable<ResourceFieldChainExpression> chains)
75+
private static IImmutableSet<IncludeElementExpression> ConvertChainsToElements(IEnumerable<ResourceFieldChainExpression> chains)
7676
{
7777
var rootNode = new MutableIncludeNode(null);
7878

@@ -81,7 +81,7 @@ private static IImmutableList<IncludeElementExpression> ConvertChainsToElements(
8181
ConvertChainToElement(chain, rootNode);
8282
}
8383

84-
return rootNode.Children.Values.Select(child => child.ToExpression()).ToImmutableArray();
84+
return rootNode.Children.Values.Select(child => child.ToExpression()).ToImmutableHashSet();
8585
}
8686

8787
private static void ConvertChainToElement(ResourceFieldChainExpression chain, MutableIncludeNode rootNode)
@@ -161,7 +161,7 @@ public MutableIncludeNode(RelationshipAttribute relationship)
161161

162162
public IncludeElementExpression ToExpression()
163163
{
164-
ImmutableArray<IncludeElementExpression> elementChildren = Children.Values.Select(child => child.ToExpression()).ToImmutableArray();
164+
IImmutableSet<IncludeElementExpression> elementChildren = Children.Values.Select(child => child.ToExpression()).ToImmutableHashSet();
165165
return new IncludeElementExpression(_relationship, elementChildren);
166166
}
167167
}

src/JsonApiDotNetCore/Queries/Expressions/IncludeElementExpression.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,14 @@ namespace JsonApiDotNetCore.Queries.Expressions
1414
public class IncludeElementExpression : QueryExpression
1515
{
1616
public RelationshipAttribute Relationship { get; }
17-
public IImmutableList<IncludeElementExpression> Children { get; }
17+
public IImmutableSet<IncludeElementExpression> Children { get; }
1818

1919
public IncludeElementExpression(RelationshipAttribute relationship)
20-
: this(relationship, ImmutableArray<IncludeElementExpression>.Empty)
20+
: this(relationship, ImmutableHashSet<IncludeElementExpression>.Empty)
2121
{
2222
}
2323

24-
public IncludeElementExpression(RelationshipAttribute relationship, IImmutableList<IncludeElementExpression> children)
24+
public IncludeElementExpression(RelationshipAttribute relationship, IImmutableSet<IncludeElementExpression> children)
2525
{
2626
ArgumentGuard.NotNull(relationship, nameof(relationship));
2727
ArgumentGuard.NotNull(children, nameof(children));
@@ -43,7 +43,7 @@ public override string ToString()
4343
if (Children.Any())
4444
{
4545
builder.Append('{');
46-
builder.Append(string.Join(",", Children.Select(child => child.ToString())));
46+
builder.Append(string.Join(",", Children.Select(child => child.ToString()).OrderBy(name => name)));
4747
builder.Append('}');
4848
}
4949

@@ -64,7 +64,7 @@ public override bool Equals(object obj)
6464

6565
var other = (IncludeElementExpression)obj;
6666

67-
return Relationship.Equals(other.Relationship) && Children.SequenceEqual(other.Children);
67+
return Relationship.Equals(other.Relationship) && Children.SetEquals(other.Children);
6868
}
6969

7070
public override int GetHashCode()

src/JsonApiDotNetCore/Queries/Expressions/IncludeExpression.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ public class IncludeExpression : QueryExpression
1616

1717
public static readonly IncludeExpression Empty = new();
1818

19-
public IImmutableList<IncludeElementExpression> Elements { get; }
19+
public IImmutableSet<IncludeElementExpression> Elements { get; }
2020

21-
public IncludeExpression(IImmutableList<IncludeElementExpression> elements)
21+
public IncludeExpression(IImmutableSet<IncludeElementExpression> elements)
2222
{
2323
ArgumentGuard.NotNullNorEmpty(elements, nameof(elements));
2424

@@ -27,7 +27,7 @@ public IncludeExpression(IImmutableList<IncludeElementExpression> elements)
2727

2828
private IncludeExpression()
2929
{
30-
Elements = ImmutableArray<IncludeElementExpression>.Empty;
30+
Elements = ImmutableHashSet<IncludeElementExpression>.Empty;
3131
}
3232

3333
public override TResult Accept<TArgument, TResult>(QueryExpressionVisitor<TArgument, TResult> visitor, TArgument argument)
@@ -38,7 +38,7 @@ public override TResult Accept<TArgument, TResult>(QueryExpressionVisitor<TArgum
3838
public override string ToString()
3939
{
4040
IReadOnlyCollection<ResourceFieldChainExpression> chains = IncludeChainConverter.GetRelationshipChains(this);
41-
return string.Join(",", chains.Select(child => child.ToString()));
41+
return string.Join(",", chains.Select(child => child.ToString()).OrderBy(name => name));
4242
}
4343

4444
public override bool Equals(object obj)
@@ -55,7 +55,7 @@ public override bool Equals(object obj)
5555

5656
var other = (IncludeExpression)obj;
5757

58-
return Elements.SequenceEqual(other.Elements);
58+
return Elements.SetEquals(other.Elements);
5959
}
6060

6161
public override int GetHashCode()

src/JsonApiDotNetCore/Queries/Expressions/QueryExpressionRewriter.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ public override QueryExpression VisitInclude(IncludeExpression expression, TArgu
268268
{
269269
if (expression != null)
270270
{
271-
IImmutableList<IncludeElementExpression> newElements = VisitList(expression.Elements, argument);
271+
IImmutableSet<IncludeElementExpression> newElements = VisitSet(expression.Elements, argument);
272272

273273
if (newElements.Count == 0)
274274
{
@@ -286,7 +286,7 @@ public override QueryExpression VisitIncludeElement(IncludeElementExpression exp
286286
{
287287
if (expression != null)
288288
{
289-
IImmutableList<IncludeElementExpression> newElements = VisitList(expression.Children, argument);
289+
IImmutableSet<IncludeElementExpression> newElements = VisitSet(expression.Children, argument);
290290

291291
var newExpression = new IncludeElementExpression(expression.Relationship, newElements);
292292
return newExpression.Equals(expression) ? expression : newExpression;

src/JsonApiDotNetCore/Queries/Internal/QueryLayerComposer.cs

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -131,21 +131,21 @@ private IncludeExpression ComposeChildren(QueryLayer topLayer, ICollection<Expre
131131
// @formatter:keep_existing_linebreaks restore
132132
// @formatter:wrap_chained_method_calls restore
133133

134-
IImmutableList<IncludeElementExpression> includeElements =
134+
IImmutableSet<IncludeElementExpression> includeElements =
135135
ProcessIncludeSet(include.Elements, topLayer, new List<RelationshipAttribute>(), constraints);
136136

137137
return !ReferenceEquals(includeElements, include.Elements)
138138
? includeElements.Any() ? new IncludeExpression(includeElements) : IncludeExpression.Empty
139139
: include;
140140
}
141141

142-
private IImmutableList<IncludeElementExpression> ProcessIncludeSet(IImmutableList<IncludeElementExpression> includeElements, QueryLayer parentLayer,
142+
private IImmutableSet<IncludeElementExpression> ProcessIncludeSet(IImmutableSet<IncludeElementExpression> includeElements, QueryLayer parentLayer,
143143
ICollection<RelationshipAttribute> parentRelationshipChain, ICollection<ExpressionInScope> constraints)
144144
{
145-
IImmutableList<IncludeElementExpression> includeElementsEvaluated =
146-
GetIncludeElements(includeElements, parentLayer.ResourceContext) ?? ImmutableArray<IncludeElementExpression>.Empty;
145+
IImmutableSet<IncludeElementExpression> includeElementsEvaluated =
146+
GetIncludeElements(includeElements, parentLayer.ResourceContext) ?? ImmutableHashSet<IncludeElementExpression>.Empty;
147147

148-
var updatesInChildren = new Dictionary<IncludeElementExpression, IImmutableList<IncludeElementExpression>>();
148+
var updatesInChildren = new Dictionary<IncludeElementExpression, IImmutableSet<IncludeElementExpression>>();
149149

150150
foreach (IncludeElementExpression includeElement in includeElementsEvaluated)
151151
{
@@ -187,7 +187,7 @@ private IImmutableList<IncludeElementExpression> ProcessIncludeSet(IImmutableLis
187187

188188
if (includeElement.Children.Any())
189189
{
190-
IImmutableList<IncludeElementExpression> updatedChildren =
190+
IImmutableSet<IncludeElementExpression> updatedChildren =
191191
ProcessIncludeSet(includeElement.Children, child, relationshipChain, constraints);
192192

193193
if (!ReferenceEquals(includeElement.Children, updatedChildren))
@@ -201,16 +201,16 @@ private IImmutableList<IncludeElementExpression> ProcessIncludeSet(IImmutableLis
201201
return !updatesInChildren.Any() ? includeElementsEvaluated : ApplyIncludeElementUpdates(includeElementsEvaluated, updatesInChildren);
202202
}
203203

204-
private static IImmutableList<IncludeElementExpression> ApplyIncludeElementUpdates(IImmutableList<IncludeElementExpression> includeElements,
205-
IDictionary<IncludeElementExpression, IImmutableList<IncludeElementExpression>> updatesInChildren)
204+
private static IImmutableSet<IncludeElementExpression> ApplyIncludeElementUpdates(IImmutableSet<IncludeElementExpression> includeElements,
205+
IDictionary<IncludeElementExpression, IImmutableSet<IncludeElementExpression>> updatesInChildren)
206206
{
207-
ImmutableArray<IncludeElementExpression>.Builder newElementsBuilder = ImmutableArray.CreateBuilder<IncludeElementExpression>(includeElements.Count);
207+
ImmutableHashSet<IncludeElementExpression>.Builder newElementsBuilder = ImmutableHashSet.CreateBuilder<IncludeElementExpression>();
208208
newElementsBuilder.AddRange(includeElements);
209209

210-
foreach ((IncludeElementExpression existingElement, IImmutableList<IncludeElementExpression> updatedChildren) in updatesInChildren)
210+
foreach ((IncludeElementExpression existingElement, IImmutableSet<IncludeElementExpression> updatedChildren) in updatesInChildren)
211211
{
212-
int existingIndex = newElementsBuilder.IndexOf(existingElement);
213-
newElementsBuilder[existingIndex] = new IncludeElementExpression(existingElement.Relationship, updatedChildren);
212+
newElementsBuilder.Remove(existingElement);
213+
newElementsBuilder.Add(new IncludeElementExpression(existingElement.Relationship, updatedChildren));
214214
}
215215

216216
return newElementsBuilder.ToImmutable();
@@ -301,7 +301,7 @@ private IncludeExpression RewriteIncludeForSecondaryEndpoint(IncludeExpression r
301301
? new IncludeElementExpression(secondaryRelationship, relativeInclude.Elements)
302302
: new IncludeElementExpression(secondaryRelationship);
303303

304-
return new IncludeExpression(ImmutableArray.Create(parentElement));
304+
return new IncludeExpression(ImmutableHashSet.Create(parentElement));
305305
}
306306

307307
private FilterExpression CreateFilterByIds<TId>(IReadOnlyCollection<TId> ids, AttrAttribute idAttribute, FilterExpression existingFilter)
@@ -329,8 +329,8 @@ public QueryLayer ComposeForUpdate<TId>(TId id, ResourceContext primaryResource)
329329
{
330330
ArgumentGuard.NotNull(primaryResource, nameof(primaryResource));
331331

332-
ImmutableArray<IncludeElementExpression> includeElements = _targetedFields.Relationships
333-
.Select(relationship => new IncludeElementExpression(relationship)).ToImmutableArray();
332+
IImmutableSet<IncludeElementExpression> includeElements = _targetedFields.Relationships
333+
.Select(relationship => new IncludeElementExpression(relationship)).ToImmutableHashSet();
334334

335335
AttrAttribute primaryIdAttribute = GetIdAttribute(primaryResource);
336336

@@ -405,7 +405,7 @@ public QueryLayer ComposeForHasMany<TId>(HasManyAttribute hasManyRelationship, T
405405

406406
return new QueryLayer(leftResourceContext)
407407
{
408-
Include = new IncludeExpression(ImmutableArray.Create(new IncludeElementExpression(hasManyRelationship))),
408+
Include = new IncludeExpression(ImmutableHashSet.Create(new IncludeElementExpression(hasManyRelationship))),
409409
Filter = leftFilter,
410410
Projection = new Dictionary<ResourceFieldAttribute, QueryLayer>
411411
{
@@ -422,7 +422,7 @@ public QueryLayer ComposeForHasMany<TId>(HasManyAttribute hasManyRelationship, T
422422
};
423423
}
424424

425-
protected virtual IImmutableList<IncludeElementExpression> GetIncludeElements(IImmutableList<IncludeElementExpression> includeElements,
425+
protected virtual IImmutableSet<IncludeElementExpression> GetIncludeElements(IImmutableSet<IncludeElementExpression> includeElements,
426426
ResourceContext resourceContext)
427427
{
428428
ArgumentGuard.NotNull(resourceContext, nameof(resourceContext));

src/JsonApiDotNetCore/Resources/IResourceDefinition.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public interface IResourceDefinition<TResource, in TId>
4444
/// <returns>
4545
/// The new set of includes. Return an empty collection to remove all inclusions (never return <c>null</c>).
4646
/// </returns>
47-
IImmutableList<IncludeElementExpression> OnApplyIncludes(IImmutableList<IncludeElementExpression> existingIncludes);
47+
IImmutableSet<IncludeElementExpression> OnApplyIncludes(IImmutableSet<IncludeElementExpression> existingIncludes);
4848

4949
/// <summary>
5050
/// Enables to extend, replace or remove a filter that is being applied on a set of this resource type.

src/JsonApiDotNetCore/Resources/IResourceDefinitionAccessor.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public interface IResourceDefinitionAccessor
1818
/// <summary>
1919
/// Invokes <see cref="IResourceDefinition{TResource,TId}.OnApplyIncludes" /> for the specified resource type.
2020
/// </summary>
21-
IImmutableList<IncludeElementExpression> OnApplyIncludes(Type resourceType, IImmutableList<IncludeElementExpression> existingIncludes);
21+
IImmutableSet<IncludeElementExpression> OnApplyIncludes(Type resourceType, IImmutableSet<IncludeElementExpression> existingIncludes);
2222

2323
/// <summary>
2424
/// Invokes <see cref="IResourceDefinition{TResource,TId}.OnApplyFilter" /> for the specified resource type.

src/JsonApiDotNetCore/Resources/JsonApiResourceDefinition.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public JsonApiResourceDefinition(IResourceGraph resourceGraph)
5252
}
5353

5454
/// <inheritdoc />
55-
public virtual IImmutableList<IncludeElementExpression> OnApplyIncludes(IImmutableList<IncludeElementExpression> existingIncludes)
55+
public virtual IImmutableSet<IncludeElementExpression> OnApplyIncludes(IImmutableSet<IncludeElementExpression> existingIncludes)
5656
{
5757
return existingIncludes;
5858
}

src/JsonApiDotNetCore/Resources/ResourceDefinitionAccessor.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public ResourceDefinitionAccessor(IResourceGraph resourceGraph, IServiceProvider
2929
}
3030

3131
/// <inheritdoc />
32-
public IImmutableList<IncludeElementExpression> OnApplyIncludes(Type resourceType, IImmutableList<IncludeElementExpression> existingIncludes)
32+
public IImmutableSet<IncludeElementExpression> OnApplyIncludes(Type resourceType, IImmutableSet<IncludeElementExpression> existingIncludes)
3333
{
3434
ArgumentGuard.NotNull(resourceType, nameof(resourceType));
3535

src/JsonApiDotNetCore/Serialization/ResponseModelAdapter.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ public Document Convert(object model)
6565
var document = new Document();
6666

6767
IncludeExpression include = _evaluatedIncludeCache.Get();
68-
IImmutableList<IncludeElementExpression> includeElements = include?.Elements ?? ImmutableArray<IncludeElementExpression>.Empty;
68+
IImmutableSet<IncludeElementExpression> includeElements = include?.Elements ?? ImmutableHashSet<IncludeElementExpression>.Empty;
6969

7070
var includedCollection = new IncludedCollection();
7171

@@ -111,7 +111,7 @@ public Document Convert(object model)
111111
return document;
112112
}
113113

114-
private AtomicResultObject ConvertOperation(OperationContainer operation, IImmutableList<IncludeElementExpression> includeElements,
114+
private AtomicResultObject ConvertOperation(OperationContainer operation, IImmutableSet<IncludeElementExpression> includeElements,
115115
IncludedCollection includedCollection)
116116
{
117117
ResourceObject resourceObject = null;
@@ -131,7 +131,7 @@ private AtomicResultObject ConvertOperation(OperationContainer operation, IImmut
131131
};
132132
}
133133

134-
private ResourceObject ConvertResource(IIdentifiable resource, EndpointKind requestKind, IImmutableList<IncludeElementExpression> includeElements,
134+
private ResourceObject ConvertResource(IIdentifiable resource, EndpointKind requestKind, IImmutableSet<IncludeElementExpression> includeElements,
135135
IncludedCollection includedCollection, bool isInclude)
136136
{
137137
ResourceContext resourceContext = _resourceGraph.GetResourceContext(resource.GetType());
@@ -203,7 +203,7 @@ private IDictionary<string, object> ConvertAttributes(IIdentifiable resource, Re
203203
}
204204

205205
private IDictionary<string, RelationshipObject> ConvertRelationships(IIdentifiable resource, ResourceContext resourceContext,
206-
IImmutableSet<ResourceFieldAttribute> fieldSet, EndpointKind requestKind, IImmutableList<IncludeElementExpression> includeElements,
206+
IImmutableSet<ResourceFieldAttribute> fieldSet, EndpointKind requestKind, IImmutableSet<IncludeElementExpression> includeElements,
207207
IncludedCollection includedCollection)
208208
{
209209
if (fieldSet != null)

test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Reading/MoonDefinition.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public MoonDefinition(IResourceGraph resourceGraph, IClientSettingsProvider clie
2525
_hitCounter = hitCounter;
2626
}
2727

28-
public override IImmutableList<IncludeElementExpression> OnApplyIncludes(IImmutableList<IncludeElementExpression> existingIncludes)
28+
public override IImmutableSet<IncludeElementExpression> OnApplyIncludes(IImmutableSet<IncludeElementExpression> existingIncludes)
2929
{
3030
_hitCounter.TrackInvocation<Moon>(ResourceDefinitionHitCounter.ExtensibilityPoint.OnApplyIncludes);
3131

test/JsonApiDotNetCoreTests/IntegrationTests/ResourceDefinitions/Reading/PlanetDefinition.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public PlanetDefinition(IResourceGraph resourceGraph, IClientSettingsProvider cl
2727
_hitCounter = hitCounter;
2828
}
2929

30-
public override IImmutableList<IncludeElementExpression> OnApplyIncludes(IImmutableList<IncludeElementExpression> existingIncludes)
30+
public override IImmutableSet<IncludeElementExpression> OnApplyIncludes(IImmutableSet<IncludeElementExpression> existingIncludes)
3131
{
3232
_hitCounter.TrackInvocation<Planet>(ResourceDefinitionHitCounter.ExtensibilityPoint.OnApplyIncludes);
3333

test/JsonApiDotNetCoreTests/UnitTests/QueryStringParameters/IncludeParseTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ public void Reader_Read_Fails(string parameterName, string parameterValue, strin
8282
[InlineData("includes", "posts.author", "posts.author")]
8383
[InlineData("includes", "posts.comments", "posts.comments")]
8484
[InlineData("includes", "posts,posts.comments", "posts.comments")]
85-
[InlineData("includes", "posts,posts.comments,posts.labels", "posts.comments,posts.labels")]
85+
[InlineData("includes", "posts,posts.labels,posts.comments", "posts.comments,posts.labels")]
8686
public void Reader_Read_Succeeds(string parameterName, string parameterValue, string valueExpected)
8787
{
8888
// Act

0 commit comments

Comments
 (0)