diff --git a/EqualityInformationApi.Tests/V1/Factories/SnsFactoryTests.cs b/EqualityInformationApi.Tests/V1/Factories/SnsFactoryTests.cs
index 68d2272..67ebcad 100644
--- a/EqualityInformationApi.Tests/V1/Factories/SnsFactoryTests.cs
+++ b/EqualityInformationApi.Tests/V1/Factories/SnsFactoryTests.cs
@@ -4,6 +4,7 @@
using EqualityInformationApi.V1.Infrastructure;
using EqualityInformationApi.V1.Infrastructure.Constants;
using FluentAssertions;
+using Hackney.Core.DynamoDb.EntityUpdater;
using Hackney.Core.JWT;
using Hackney.Core.Sns;
using System;
diff --git a/EqualityInformationApi.Tests/V1/Gateways/DynamoDbGatewayTests.cs b/EqualityInformationApi.Tests/V1/Gateways/DynamoDbGatewayTests.cs
index 5a897d8..ce684e1 100644
--- a/EqualityInformationApi.Tests/V1/Gateways/DynamoDbGatewayTests.cs
+++ b/EqualityInformationApi.Tests/V1/Gateways/DynamoDbGatewayTests.cs
@@ -8,6 +8,8 @@
using EqualityInformationApi.V1.Infrastructure.Exceptions;
using FluentAssertions;
using Force.DeepCloner;
+using Hackney.Core.DynamoDb.EntityUpdater;
+using Hackney.Core.DynamoDb.EntityUpdater.Interfaces;
using Hackney.Core.Testing.DynamoDb;
using Microsoft.Extensions.Logging;
using Moq;
diff --git a/EqualityInformationApi.Tests/V1/Infrastructure/StringExtensionsTests.cs b/EqualityInformationApi.Tests/V1/Infrastructure/StringExtensionsTests.cs
deleted file mode 100644
index 7345f2b..0000000
--- a/EqualityInformationApi.Tests/V1/Infrastructure/StringExtensionsTests.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-using FluentAssertions;
-using Xunit;
-
-namespace Hackney.Core.Tests
-{
- public class StringExtensionsTests
- {
- [Theory]
- [InlineData(null, null)]
- [InlineData("", "")]
- [InlineData("c", "c")]
- [InlineData("C", "c")]
- [InlineData("camel", "camel")]
- [InlineData("Camel", "camel")]
- [InlineData("oneHumpCamel", "oneHumpCamel")]
- [InlineData("OneHumpCamel", "oneHumpCamel")]
- public void ToCamelCaseTests(string input, string expectedOutput)
- {
- input.ToCamelCase().Should().Be(expectedOutput);
- }
- }
-}
diff --git a/EqualityInformationApi.Tests/V1/UseCase/PatchUseCaseTests.cs b/EqualityInformationApi.Tests/V1/UseCase/PatchUseCaseTests.cs
index c71f890..95ce8c3 100644
--- a/EqualityInformationApi.Tests/V1/UseCase/PatchUseCaseTests.cs
+++ b/EqualityInformationApi.Tests/V1/UseCase/PatchUseCaseTests.cs
@@ -5,6 +5,7 @@
using EqualityInformationApi.V1.Infrastructure;
using EqualityInformationApi.V1.UseCase;
using FluentAssertions;
+using Hackney.Core.DynamoDb.EntityUpdater;
using Hackney.Core.JWT;
using Hackney.Core.Sns;
using Moq;
diff --git a/EqualityInformationApi/EqualityInformationApi.csproj b/EqualityInformationApi/EqualityInformationApi.csproj
index 58c3c60..712f9b7 100644
--- a/EqualityInformationApi/EqualityInformationApi.csproj
+++ b/EqualityInformationApi/EqualityInformationApi.csproj
@@ -22,11 +22,11 @@
-
+
-
+
diff --git a/EqualityInformationApi/Startup.cs b/EqualityInformationApi/Startup.cs
index 1828349..05ce356 100644
--- a/EqualityInformationApi/Startup.cs
+++ b/EqualityInformationApi/Startup.cs
@@ -41,6 +41,8 @@
using System.Text.Json.Serialization;
using HeaderConstants = EqualityInformationApi.V1.Infrastructure.HeaderConstants;
using CoreHeaderConstants = Hackney.Core.Middleware.HeaderConstants;
+using Hackney.Core.DynamoDb.EntityUpdater;
+using Hackney.Core.DynamoDb.EntityUpdater.Interfaces;
namespace EqualityInformationApi
{
diff --git a/EqualityInformationApi/V1/Factories/ISnsFactory.cs b/EqualityInformationApi/V1/Factories/ISnsFactory.cs
index 220ea08..79e9420 100644
--- a/EqualityInformationApi/V1/Factories/ISnsFactory.cs
+++ b/EqualityInformationApi/V1/Factories/ISnsFactory.cs
@@ -1,5 +1,6 @@
using EqualityInformationApi.V1.Domain;
using EqualityInformationApi.V1.Infrastructure;
+using Hackney.Core.DynamoDb.EntityUpdater;
using Hackney.Core.JWT;
using Hackney.Core.Sns;
diff --git a/EqualityInformationApi/V1/Factories/SnsFactory.cs b/EqualityInformationApi/V1/Factories/SnsFactory.cs
index f378dc9..e4d4a5e 100644
--- a/EqualityInformationApi/V1/Factories/SnsFactory.cs
+++ b/EqualityInformationApi/V1/Factories/SnsFactory.cs
@@ -1,6 +1,7 @@
using EqualityInformationApi.V1.Domain;
using EqualityInformationApi.V1.Infrastructure;
using EqualityInformationApi.V1.Infrastructure.Constants;
+using Hackney.Core.DynamoDb.EntityUpdater;
using Hackney.Core.JWT;
using Hackney.Core.Sns;
using System;
diff --git a/EqualityInformationApi/V1/Gateways/EqualityInformationGateway.cs b/EqualityInformationApi/V1/Gateways/EqualityInformationGateway.cs
index ee3b306..965c208 100644
--- a/EqualityInformationApi/V1/Gateways/EqualityInformationGateway.cs
+++ b/EqualityInformationApi/V1/Gateways/EqualityInformationGateway.cs
@@ -4,6 +4,8 @@
using EqualityInformationApi.V1.Factories;
using EqualityInformationApi.V1.Infrastructure;
using EqualityInformationApi.V1.Infrastructure.Exceptions;
+using Hackney.Core.DynamoDb.EntityUpdater;
+using Hackney.Core.DynamoDb.EntityUpdater.Interfaces;
using Hackney.Core.Logging;
using Microsoft.Extensions.Logging;
using System;
diff --git a/EqualityInformationApi/V1/Gateways/IEqualityInformationGateway.cs b/EqualityInformationApi/V1/Gateways/IEqualityInformationGateway.cs
index 792a970..d9e35d0 100644
--- a/EqualityInformationApi/V1/Gateways/IEqualityInformationGateway.cs
+++ b/EqualityInformationApi/V1/Gateways/IEqualityInformationGateway.cs
@@ -1,6 +1,7 @@
using EqualityInformationApi.V1.Boundary.Request;
using EqualityInformationApi.V1.Domain;
using EqualityInformationApi.V1.Infrastructure;
+using Hackney.Core.DynamoDb.EntityUpdater;
using System;
using System.Threading.Tasks;
diff --git a/EqualityInformationApi/V1/Infrastructure/BodyRewind.cs b/EqualityInformationApi/V1/Infrastructure/BodyRewind.cs
deleted file mode 100644
index 0d27428..0000000
--- a/EqualityInformationApi/V1/Infrastructure/BodyRewind.cs
+++ /dev/null
@@ -1,45 +0,0 @@
-using Microsoft.AspNetCore.Builder;
-using Microsoft.AspNetCore.Http;
-using System;
-using System.Diagnostics.CodeAnalysis;
-using System.Threading.Tasks;
-
-namespace Hackney.Core.Middleware
-{
- // TODO - move to common nuget package
-
- [ExcludeFromCodeCoverage]
- public sealed class BodyRewindMiddleware
- {
- private readonly RequestDelegate _next;
-
- public BodyRewindMiddleware(RequestDelegate next)
- {
- _next = next;
- }
-
- public async Task Invoke(HttpContext context)
- {
- context.Request.EnableBuffering();
- await _next(context).ConfigureAwait(false);
- }
- }
-
- [ExcludeFromCodeCoverage]
- public static class BodyRewindExtensions
- {
- ///
- /// Enables the HttpRequset body to be access from within a controller method.
- /// Without this the request body is rendered unaccessible by other middleware steps.
- ///
- /// An App builder
- /// An App builder
- public static IApplicationBuilder EnableRequestBodyRewind(this IApplicationBuilder app)
- {
- if (app == null) throw new ArgumentNullException(nameof(app));
-
- return app.UseMiddleware();
- }
-
- }
-}
diff --git a/EqualityInformationApi/V1/Infrastructure/EntityUpdater.cs b/EqualityInformationApi/V1/Infrastructure/EntityUpdater.cs
deleted file mode 100644
index 657c68f..0000000
--- a/EqualityInformationApi/V1/Infrastructure/EntityUpdater.cs
+++ /dev/null
@@ -1,131 +0,0 @@
-using Hackney.Core;
-using Microsoft.Extensions.Logging;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text.Json;
-using System.Text.Json.Serialization;
-
-namespace EqualityInformationApi.V1.Infrastructure
-{
- // TODO - move to common nuget package
-
- public class EntityUpdater : IEntityUpdater
- {
- private readonly ILogger _logger;
-
- public EntityUpdater(ILogger logger)
- {
- _logger = logger;
- }
-
- private static JsonSerializerOptions CreateJsonOptions()
- {
- var options = new JsonSerializerOptions
- {
- PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
- WriteIndented = true
- };
- options.Converters.Add(new JsonStringEnumConverter());
- return options;
- }
-
- private static bool HasValueChanged(object existingValue, object updateValue)
- {
- if (updateValue is null && existingValue is null) return false;
- if (updateValue is null && (existingValue != null)) return true;
- return !updateValue.Equals(existingValue);
- }
-
- ///
- /// Updates the supplied entity with the updated property values described in the request object / json
- /// Defaults the ignoreUnchangedProperties input value to true.
- ///
- /// The entity type
- /// The type of the update request object
- /// The entity to update
- /// The raw update request json from which the request object was deserialized
- /// The update request object
- /// A response object
- public UpdateEntityResult UpdateEntity(TEntity entityToUpdate,
- string updateJson,
- TUpdateObject updateObject)
- where TEntity : class
- where TUpdateObject : class
- {
- return UpdateEntity(entityToUpdate, updateJson, updateObject, true);
- }
-
- ///
- /// Updates the supplied entity with the updated property values described in the request object / json.
- /// * This method expects both a request object and the raw request json so that the appropriate request object validation
- /// can be executed by the MVC pipeline.
- /// * The inclusion of the request object also means that each updated property value has been deserialised correctly.
- /// * The raw request json should contain ONLY the properties to be updated.
- /// * The property names in the json / request object MUST MATCH the corresponing properties on the entity type (assuming the json uses camel casing).
- /// * For nested objects, those classes must override the Equals() mewthod so that the algorithm will correctly determine if a suboject has changed.
- ///
- /// The entity type
- /// The type of the update request object
- /// The entity to update
- /// The raw update request json from which the request object was deserialized
- /// The update request object
- /// Whether or not to ignore property values set in the update request
- /// but that are actually the same as current entity value.
- /// A response object
- public UpdateEntityResult UpdateEntity(TEntity entityToUpdate,
- string updateJson,
- TUpdateObject updateObject,
- bool ignoreUnchangedProperties)
- where TEntity : class
- where TUpdateObject : class
- {
- if (entityToUpdate is null) throw new ArgumentNullException(nameof(entityToUpdate));
- if (updateObject is null) throw new ArgumentNullException(nameof(updateObject));
-
- var result = new UpdateEntityResult() { UpdatedEntity = entityToUpdate };
- if (string.IsNullOrEmpty(updateJson)) return result;
-
- var updateDic = JsonSerializer.Deserialize>(updateJson, CreateJsonOptions());
- var entityType = typeof(TEntity);
- var updateObjectType = typeof(TUpdateObject);
-
- var allEntityProperties = entityType.GetProperties();
- foreach (var propName in updateDic.Keys)
- {
- var prop = allEntityProperties.FirstOrDefault(x => x.Name.ToCamelCase() == propName);
- if (prop is null)
- {
- // Received a property on the request Json that's not on the entity at all
- // So we log a warning, ignore it and carry on.
- _logger.LogWarning($"Entity object (type: {entityType.Name}) does not contain a property called {propName}. Ignoring {propName} value...");
- result.IgnoredProperties.Add(propName);
- continue;
- }
-
- var requestObjectProperty = updateObjectType.GetProperty(prop.Name);
- if (requestObjectProperty is null)
- {
- // Received a property on the request Json we weren't expecting (it's not on the request object)
- // So we log a warning, ignore it and carry on.
- _logger.LogWarning($"Request object (type: {updateObjectType.Name}) does not contain a property called {prop.Name} that is on the entity type ({entityType.Name}). Ignoring {prop.Name} value...");
- result.IgnoredProperties.Add(propName);
- continue;
- }
-
- var updateValue = requestObjectProperty.GetValue(updateObject);
- var existingValue = prop.GetValue(entityToUpdate);
-
- // For sub-objects this Equals() check will only work if the Equals() method is overridden
- if (!ignoreUnchangedProperties || HasValueChanged(existingValue, updateValue))
- {
- result.OldValues.Add(propName, existingValue);
- result.NewValues.Add(propName, updateValue);
- prop.SetValue(entityToUpdate, updateValue);
- }
- }
-
- return result;
- }
- }
-}
diff --git a/EqualityInformationApi/V1/Infrastructure/IEntityUpdater.cs b/EqualityInformationApi/V1/Infrastructure/IEntityUpdater.cs
deleted file mode 100644
index 10765d6..0000000
--- a/EqualityInformationApi/V1/Infrastructure/IEntityUpdater.cs
+++ /dev/null
@@ -1,49 +0,0 @@
-namespace EqualityInformationApi.V1.Infrastructure
-{
- // TODO - move to common nuget package
-
- ///
- /// Interface describing generic methods for updating an instance of an entity from the suypplied request object and raw request json
- ///
- public interface IEntityUpdater
- {
- ///
- /// Updates the supplied entity with the updated property values described in the request object / json
- ///
- /// The entity type
- /// The type of the update request object
- /// The entity to update
- /// The raw update request json from which the request object was deserialized
- /// The update request object
- /// A response object
- UpdateEntityResult UpdateEntity(
- TEntity entityToUpdate,
- string updateJson,
- TUpdateObject updateObject)
- where TEntity : class
- where TUpdateObject : class;
-
- ///
- /// Updates the supplied entity with the updated property values described in the request object / json.
- /// * This method expects both a request object and the raw request json so that the appropriate request object validation
- /// can be executed by the MVC pipeline.
- /// * The raw request json should contain ONLY the properties to be updated.
- /// * The property names in the json / request object MUST MATCH the corresponing properties on the entity type (assuming the json uses camel casing).
- ///
- /// The entity type
- /// The type of the update request object
- /// The entity to update
- /// The raw update request json from which the request object was deserialized
- /// The update request object
- /// Whether or not to ignore property values set in the update request
- /// but that are actually the same as current entity value.
- /// A response object
- UpdateEntityResult UpdateEntity(
- TEntity entityToUpdate,
- string updateJson,
- TUpdateObject updateObject,
- bool ignoreUnchangedProperties)
- where TEntity : class
- where TUpdateObject : class;
- }
-}
diff --git a/EqualityInformationApi/V1/Infrastructure/StringExtensions.cs b/EqualityInformationApi/V1/Infrastructure/StringExtensions.cs
deleted file mode 100644
index f394b38..0000000
--- a/EqualityInformationApi/V1/Infrastructure/StringExtensions.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-namespace Hackney.Core
-{
- // TODO - move to common nuget package
-
- public static class StringExtensions
- {
- ///
- /// Converts the string to camel case (i.e. the first character is lowercase)
- ///
- /// The string to change
- /// A copied of the string with the first chacater in lowercase. A null or empty string returns what was supplied.
- ///
- public static string ToCamelCase(this string str)
- {
- if (string.IsNullOrEmpty(str)) return str;
- if (str.Length == 1) return str.ToLowerInvariant();
-
- // else if (str.Length > 1)
- return char.ToLowerInvariant(str[0]) + str.Substring(1);
- }
- }
-}
diff --git a/EqualityInformationApi/V1/Infrastructure/UpdateEntityResult.cs b/EqualityInformationApi/V1/Infrastructure/UpdateEntityResult.cs
deleted file mode 100644
index 9b4f40f..0000000
--- a/EqualityInformationApi/V1/Infrastructure/UpdateEntityResult.cs
+++ /dev/null
@@ -1,31 +0,0 @@
-using System.Collections.Generic;
-
-namespace EqualityInformationApi.V1.Infrastructure
-{
- public class UpdateEntityResult where T : class
- {
- ///
- /// The updated entity
- ///
- public T UpdatedEntity { get; set; }
-
- ///
- /// A simple dictionary listing the previous value(s) of any entity properties actually updated by the call.
- /// The size and keys of this dictionary will match that of the NewValues property.
- ///
- public Dictionary OldValues { get; set; } = new Dictionary();
-
- ///
- /// A simple dictionary listing the new value(s) of any entity properties actually updated by the call.
- /// The size and keys of this dictionary will match that of the OldValues property.
- ///
- public Dictionary NewValues { get; set; } = new Dictionary();
-
- ///
- /// A collection of properties that were in the orignal request json but that were ignored because either
- /// * They did not exist on the request object, or
- /// * They did not exist on the entity at all.
- ///
- public List IgnoredProperties { get; set; } = new List();
- }
-}