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