feat: refactored entity sequences and added tests
This commit is contained in:
parent
86403060e7
commit
74caa6eefd
7 changed files with 166 additions and 68 deletions
33
src/Nitride/Entities/EntitySequence.cs
Normal file
33
src/Nitride/Entities/EntitySequence.cs
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
using Gallium;
|
||||||
|
|
||||||
|
namespace Nitride.Entities;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Defines a relationship between a given entity and the others in a sequence.
|
||||||
|
/// </summary>
|
||||||
|
public class EntitySequence
|
||||||
|
{
|
||||||
|
public EntitySequence(IReadOnlyList<Entity> sequence, int index)
|
||||||
|
{
|
||||||
|
this.Sequence = sequence;
|
||||||
|
this.Index = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool HasNext => !this.IsLast;
|
||||||
|
|
||||||
|
public bool HasPrevious => !this.IsFirst;
|
||||||
|
|
||||||
|
public int Index { get; }
|
||||||
|
|
||||||
|
public bool IsFirst => this.Index == 0;
|
||||||
|
|
||||||
|
public bool IsLast => this.Index == this.Sequence.Count - 1;
|
||||||
|
|
||||||
|
public Entity? Next => this.HasNext ? this.Sequence[this.Index + 1] : null;
|
||||||
|
|
||||||
|
public Entity? Previous => this.HasPrevious ? this.Sequence[this.Index - 1] : null;
|
||||||
|
|
||||||
|
public IReadOnlyList<Entity> Sequence { get; }
|
||||||
|
}
|
58
src/Nitride/Entities/LinkEntitySequence.cs
Normal file
58
src/Nitride/Entities/LinkEntitySequence.cs
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
using FluentValidation;
|
||||||
|
|
||||||
|
using Gallium;
|
||||||
|
|
||||||
|
namespace Nitride.Entities;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Links a series of entities together in some manner. This assumes that
|
||||||
|
/// the entities coming into the operation are already ordered.
|
||||||
|
/// </summary>
|
||||||
|
[WithProperties]
|
||||||
|
public partial class LinkEntitySequence : OperationBase, IResolvingOperation
|
||||||
|
{
|
||||||
|
private readonly IValidator<LinkEntitySequence> validator;
|
||||||
|
|
||||||
|
public LinkEntitySequence(IValidator<LinkEntitySequence> validator)
|
||||||
|
{
|
||||||
|
this.validator = validator;
|
||||||
|
this.CreateSequenceIndex = (list, index) => new EntitySequence(list, index);
|
||||||
|
this.AddSequenceIndex = (entity, sequence) => entity.Add(sequence);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a callback to add a sequence into a given entity.
|
||||||
|
/// </summary>
|
||||||
|
public Func<Entity, EntitySequence, Entity> AddSequenceIndex { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the function used to create the sequence index.
|
||||||
|
/// </summary>
|
||||||
|
public Func<IReadOnlyList<Entity>, int, EntitySequence> CreateSequenceIndex { get; set; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override IEnumerable<Entity> Run(IEnumerable<Entity> input)
|
||||||
|
{
|
||||||
|
// Make sure everything is good.
|
||||||
|
this.validator.ValidateAndThrow(this);
|
||||||
|
|
||||||
|
// We pull all the entities into a list so we can walk through them
|
||||||
|
// more than once along with index access. We also don't reorder the
|
||||||
|
// list since we assumed it has been ordered already.
|
||||||
|
var list = input.ToList();
|
||||||
|
|
||||||
|
// Go through the list and assign each entity in order with a unique
|
||||||
|
// copy of the sequence.
|
||||||
|
for (int i = 0; i < list.Count; i++)
|
||||||
|
{
|
||||||
|
Entity entity = list[i];
|
||||||
|
EntitySequence index = this.CreateSequenceIndex(list.AsReadOnly(), i);
|
||||||
|
|
||||||
|
yield return this.AddSequenceIndex(entity, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
12
src/Nitride/Entities/LinkEntitySequenceValidator.cs
Normal file
12
src/Nitride/Entities/LinkEntitySequenceValidator.cs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
using FluentValidation;
|
||||||
|
|
||||||
|
namespace Nitride.Entities;
|
||||||
|
|
||||||
|
public class LinkEntitySequenceValidator : AbstractValidator<LinkEntitySequence>
|
||||||
|
{
|
||||||
|
public LinkEntitySequenceValidator()
|
||||||
|
{
|
||||||
|
this.RuleFor(x => x.CreateSequenceIndex).NotNull();
|
||||||
|
this.RuleFor(x => x.AddSequenceIndex).NotNull();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +0,0 @@
|
||||||
using Gallium;
|
|
||||||
|
|
||||||
namespace Nitride.Entities;
|
|
||||||
|
|
||||||
public delegate Entity LinkPreviousNextHandler(Entity entity, Entity? previous, Entity? next);
|
|
|
@ -1,52 +0,0 @@
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
using FluentValidation;
|
|
||||||
|
|
||||||
using Gallium;
|
|
||||||
|
|
||||||
namespace Nitride.Entities;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Links a series of entities together in some manner. This assumes that
|
|
||||||
/// the entities coming into the operation are already ordered.
|
|
||||||
/// </summary>
|
|
||||||
[WithProperties]
|
|
||||||
public partial class LinkSerialEntities : OperationBase
|
|
||||||
{
|
|
||||||
private readonly IValidator<LinkSerialEntities> validator;
|
|
||||||
|
|
||||||
public LinkSerialEntities(IValidator<LinkSerialEntities> validator)
|
|
||||||
{
|
|
||||||
this.validator = validator;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The callback function that sets the previous and next
|
|
||||||
/// </summary>
|
|
||||||
public LinkPreviousNextHandler? UpdatePreviousNext { get; set; }
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override IEnumerable<Entity> Run(IEnumerable<Entity> input)
|
|
||||||
{
|
|
||||||
// Make sure everything is good.
|
|
||||||
this.validator.ValidateAndThrow(this);
|
|
||||||
|
|
||||||
// We pull all the entities into a list so we can walk through them
|
|
||||||
// more than once along with index access.
|
|
||||||
var list = input.ToList();
|
|
||||||
|
|
||||||
// Go through the list and assign each entity in order.
|
|
||||||
for (int i = 0; i < list.Count; i++)
|
|
||||||
{
|
|
||||||
Entity entity = list[i];
|
|
||||||
Entity? previous = i > 0 ? list[i - 1] : null;
|
|
||||||
Entity? next = i < list.Count - 1 ? list[i + 1] : null;
|
|
||||||
|
|
||||||
list[i] = this.UpdatePreviousNext!(entity, previous, next);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return the resulting list.
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
using FluentValidation;
|
|
||||||
|
|
||||||
namespace Nitride.Entities;
|
|
||||||
|
|
||||||
public class LinkSerialEntitiesValidator : AbstractValidator<LinkSerialEntities>
|
|
||||||
{
|
|
||||||
public LinkSerialEntitiesValidator()
|
|
||||||
{
|
|
||||||
this.RuleFor(x => x.UpdatePreviousNext).NotNull();
|
|
||||||
}
|
|
||||||
}
|
|
63
tests/Nitride.Tests/Entities/LinkEntitySequenceTests.cs
Normal file
63
tests/Nitride.Tests/Entities/LinkEntitySequenceTests.cs
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
using Gallium;
|
||||||
|
|
||||||
|
using Nitride.Entities;
|
||||||
|
|
||||||
|
using Xunit;
|
||||||
|
using Xunit.Abstractions;
|
||||||
|
|
||||||
|
namespace Nitride.Tests.Entities;
|
||||||
|
|
||||||
|
public class LinkEntitySequenceTests : NitrideTestBase
|
||||||
|
{
|
||||||
|
public LinkEntitySequenceTests(ITestOutputHelper output)
|
||||||
|
: base(output)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void LinkThree()
|
||||||
|
{
|
||||||
|
NitrideTestContext context = this.CreateContext();
|
||||||
|
LinkEntitySequence op = context.Resolve<LinkEntitySequence>();
|
||||||
|
|
||||||
|
var input = new List<Entity>
|
||||||
|
{
|
||||||
|
new Entity().Add("page1"),
|
||||||
|
new Entity().Add("page2"),
|
||||||
|
new Entity().Add("page3"),
|
||||||
|
};
|
||||||
|
|
||||||
|
var results = op.Run(input).ToList();
|
||||||
|
|
||||||
|
Assert.Equal(3, results.Count);
|
||||||
|
|
||||||
|
EntitySequence seq1 = results[0].Get<EntitySequence>();
|
||||||
|
EntitySequence seq2 = results[1].Get<EntitySequence>();
|
||||||
|
EntitySequence seq3 = results[2].Get<EntitySequence>();
|
||||||
|
|
||||||
|
Assert.True(seq1.IsFirst);
|
||||||
|
Assert.False(seq1.IsLast);
|
||||||
|
Assert.False(seq1.HasPrevious);
|
||||||
|
Assert.True(seq1.HasNext);
|
||||||
|
Assert.Null(seq1.Previous?.Get<string>());
|
||||||
|
Assert.Equal("page2", seq1.Next!.Get<string>());
|
||||||
|
|
||||||
|
Assert.False(seq2.IsFirst);
|
||||||
|
Assert.False(seq2.IsLast);
|
||||||
|
Assert.True(seq2.HasPrevious);
|
||||||
|
Assert.True(seq2.HasNext);
|
||||||
|
Assert.Equal("page1", seq2.Previous!.Get<string>());
|
||||||
|
Assert.Equal("page3", seq2.Next!.Get<string>());
|
||||||
|
|
||||||
|
Assert.False(seq3.IsFirst);
|
||||||
|
Assert.True(seq3.IsLast);
|
||||||
|
Assert.True(seq3.HasPrevious);
|
||||||
|
Assert.False(seq3.HasNext);
|
||||||
|
Assert.Equal("page2", seq3.Previous!.Get<string>());
|
||||||
|
Assert.Null(seq3.Next?.Get<string>());
|
||||||
|
}
|
||||||
|
}
|
Reference in a new issue