Skip to content

Commit

Permalink
Merge pull request #17 from davewalker5/FR-24-Bug-Fixes
Browse files Browse the repository at this point in the history
Support minimal aircraft properties (registration only)
  • Loading branch information
davewalker5 committed Oct 23, 2023
2 parents 7d36f4c + d71da5f commit e0d6dda
Show file tree
Hide file tree
Showing 51 changed files with 1,015 additions and 1,603 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@

namespace FlightRecorder.BusinessLogic.Extensions
{
public static class FlightRecorderStringExtensions
public static partial class FlightRecorderStringExtensions
{
public static string CleanString(this string input)
{
return Regex.Replace(input, @"\t|\n|\r", "").Replace(" ", " ").Trim();
return MyRegex().Replace(input ?? "", "").Replace(" ", " ").Trim();
}

[GeneratedRegex("\\t|\\n|\\r")]
private static partial Regex MyRegex();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<PackageId>FlightRecorder.BusinessLogic</PackageId>
<PackageVersion>1.1.1.0</PackageVersion>
<PackageVersion>1.1.3.0</PackageVersion>
<Authors>Dave Walker</Authors>
<Copyright>Copyright (c) Dave Walker 2020, 2021, 2022, 2023</Copyright>
<Owners>Dave Walker</Owners>
Expand All @@ -16,7 +16,7 @@
<PackageProjectUrl>https://github.com/davewalker5/FlightRecorderDb</PackageProjectUrl>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
<ReleaseVersion>1.1.1.0</ReleaseVersion>
<ReleaseVersion>1.1.3.0</ReleaseVersion>
</PropertyGroup>

<ItemGroup>
Expand Down
157 changes: 24 additions & 133 deletions src/FlightRecorder.BusinessLogic/Logic/AircraftManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,59 +22,17 @@ internal AircraftManager(FlightRecorderFactory factory)
_factory = factory;
}

/// <summary>
/// Get the first aircraft matching the specified criteria along with the associated model
/// </summary>
/// <param name="predicate"></param>
/// <returns></returns>
public Aircraft Get(Expression<Func<Aircraft, bool>> predicate)
=> List(predicate, 1, 1).FirstOrDefault();

/// <summary>
/// Get the first aircraft matching the specified criteria along with the associated model
/// </summary>
/// <param name="predicate"></param>
/// <returns></returns>
public async Task<Aircraft> GetAsync(Expression<Func<Aircraft, bool>> predicate)
{
List<Aircraft> aircraft = await _factory.Context.Aircraft
.Where(predicate)
.ToListAsync();
List<Aircraft> aircraft = await ListAsync(predicate, 1, 1).ToListAsync();
return aircraft.FirstOrDefault();
}

/// <summary>
/// Get the aircraft matching the specified criteria along with the associated models
/// </summary>
/// <param name="predicate"></param>
/// <param name="pageNumber"></param>
/// <param name="pageSize"></param>
/// <returns></returns>
public IEnumerable<Aircraft> List(Expression<Func<Aircraft, bool>> predicate, int pageNumber, int pageSize)
{
IEnumerable<Aircraft> aircraft;

if (predicate == null)
{
aircraft = _factory.Context.Aircraft
.Include(a => a.Model)
.ThenInclude(m => m.Manufacturer)
.Skip((pageNumber - 1) * pageSize)
.Take(pageSize);
}
else
{
aircraft = _factory.Context.Aircraft
.Include(a => a.Model)
.ThenInclude(m => m.Manufacturer)
.Where(predicate)
.Skip((pageNumber - 1) * pageSize)
.Take(pageSize);
}

return aircraft;
}

/// <summary>
/// Get the aircraft matching the specified criteria along with the associated models
/// </summary>
Expand Down Expand Up @@ -109,27 +67,6 @@ public IAsyncEnumerable<Aircraft> ListAsync(Expression<Func<Aircraft, bool>> pre
return aircraft;
}

/// <summary>
/// Get the aircraft of a specified model
/// </summary>
/// <param name="modelName"></param>
/// <param name="pageNumber"></param>
/// <param name="pageSize"></param>
/// <returns></returns>
public IEnumerable<Aircraft> ListByModel(string modelName, int pageNumber, int pageSize)
{
IEnumerable<Aircraft> matches = null;

modelName = modelName.CleanString();
Model model = _factory.Models.Get(m => m.Name == modelName);
if (model != null)
{
matches = List(m => m.ModelId == model.Id, pageNumber, pageSize);
}

return matches;
}

/// <summary>
/// Get the aircraft of a specified model
/// </summary>
Expand All @@ -151,35 +88,6 @@ public async Task<IAsyncEnumerable<Aircraft>> ListByModelAsync(string modelName,
return matches;
}

/// <summary>
/// Get the aircraft manufactured by a given manufacturer
/// </summary>
/// <param name="manufacturerName"></param>
/// <param name="pageNumber"></param>
/// <param name="pageSize"></param>
/// <returns></returns>
public IEnumerable<Aircraft> ListByManufacturer(string manufacturerName, int pageNumber, int pageSize)
{
IEnumerable<Aircraft> matches = null;

manufacturerName = manufacturerName.CleanString();
Manufacturer manufacturer = _factory.Manufacturers
.Get(m => m.Name == manufacturerName);
if (manufacturer != null)
{
// Model retrieval uses an arbitrarily large page size to retrieve all models
IEnumerable<long> modelIds = _factory.Models
.List(m => m.ManufacturerId == manufacturer.Id, 1, AllModelsPageSize)
.Select(m => m.Id);
if (modelIds.Any())
{
matches = List(a => modelIds.Contains(a.ModelId), pageNumber, pageSize);
}
}

return matches;
}

/// <summary>
/// Get the aircraft manufactured by a given manufacturer
/// </summary>
Expand All @@ -203,7 +111,7 @@ public async Task<IAsyncEnumerable<Aircraft>> ListByManufacturerAsync(string man
.ToListAsync();
if (modelIds.Any())
{
matches = ListAsync(a => modelIds.Contains(a.ModelId), pageNumber, pageSize);
matches = ListAsync(a => modelIds.Contains(a.ModelId ?? -1), pageNumber, pageSize);
}
}

Expand All @@ -219,62 +127,45 @@ public async Task<IAsyncEnumerable<Aircraft>> ListByManufacturerAsync(string man
/// <param name="model"></param>
/// <param name="manufacturer"></param>
/// <returns></returns>
public Aircraft Add(string registration, string serialNumber, long? yearOfManufacture, string modelName, string manufacturerName)
public async Task<Aircraft> AddAsync(string registration, string serialNumber, long? yearOfManufacture, string modelName, string manufacturerName)
{
registration = registration.CleanString().ToUpper();
Aircraft aircraft = Get(a => a.Registration == registration);
Aircraft aircraft = await GetAsync(a => a.Registration == registration);

if (aircraft == null)
{
Model model = _factory.Models.Add(modelName, manufacturerName);

aircraft = new Aircraft
// If partial aircraft details have been supplied, the manufacturer and/or model may not
// be specified
long? modelId = null;
if (!string.IsNullOrEmpty(manufacturerName) && !string.IsNullOrEmpty(modelName))
{
Registration = registration,
SerialNumber = serialNumber.CleanString().ToUpper(),
Manufactured = yearOfManufacture,
ModelId = model.Id
};
Model model = await _factory.Models.AddAsync(modelName, manufacturerName);
modelId = model.Id;
}

_factory.Context.Add(aircraft);
_factory.Context.SaveChanges();
_factory.Context.Entry(aircraft).Reference(m => m.Model).Load();
_factory.Context.Entry(aircraft.Model).Reference(m => m.Manufacturer).Load();
}
// Similarly, the serial number should be cleaned and then treated as null when assigning
// to the new aircraft, below, if the result is empty
var cleanSerialNumber = serialNumber.CleanString().ToUpper();
var haveSerialNumber = !string.IsNullOrEmpty(cleanSerialNumber);

return aircraft;
}

/// <summary>
/// Add an aircraft
/// </summary>
/// <param name="registration"></param>
/// <param name="serialNumber"></param>
/// <param name="yearOfManufacture"></param>
/// <param name="model"></param>
/// <param name="manufacturer"></param>
/// <returns></returns>
public async Task<Aircraft> AddAsync(string registration, string serialNumber, long? yearOfManufacture, string modelName, string manufacturerName)
{
registration = registration.CleanString().ToUpper();
Aircraft aircraft = await GetAsync(a => a.Registration == registration);

if (aircraft == null)
{
Model model = await _factory.Models.AddAsync(modelName, manufacturerName);
// Finally, year of manufacture should only be stored if we have a model or serial number
long? manufactured = haveSerialNumber && (modelId != null) ? yearOfManufacture : null;

aircraft = new Aircraft
{
Registration = registration,
SerialNumber = serialNumber.CleanString().ToUpper(),
Manufactured = yearOfManufacture,
ModelId = model.Id
SerialNumber = haveSerialNumber ? cleanSerialNumber : null,
Manufactured = manufactured,
ModelId = modelId
};

await _factory.Context.AddAsync(aircraft);
await _factory.Context.SaveChangesAsync();
await _factory.Context.Entry(aircraft).Reference(m => m.Model).LoadAsync();
await _factory.Context.Entry(aircraft.Model).Reference(m => m.Manufacturer).LoadAsync();
if (aircraft.Model != null)
{
await _factory.Context.Entry(aircraft.Model).Reference(m => m.Manufacturer).LoadAsync();
}
}

return aircraft;
Expand Down
59 changes: 1 addition & 58 deletions src/FlightRecorder.BusinessLogic/Logic/AirlineManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,54 +20,17 @@ internal AirlineManager(FlightRecorderDbContext context)
_context = context;
}

/// <summary>
/// Return the first entity matching the specified criteria
/// </summary>
/// <param name="predicate"></param>
/// <returns></returns>
public Airline Get(Expression<Func<Airline, bool>> predicate)
=> List(predicate, 1, 1).FirstOrDefault();

/// <summary>
/// Get the first airline matching the specified criteria
/// </summary>
/// <param name="predicate"></param>
/// <returns></returns>
public async Task<Airline> GetAsync(Expression<Func<Airline, bool>> predicate)
{
List<Airline> airlines = await _context.Airlines
.Where(predicate)
.ToListAsync();
List<Airline> airlines = await ListAsync(predicate, 1, 1).ToListAsync();
return airlines.FirstOrDefault();
}

/// <summary>
/// Return all entities matching the specified criteria
/// </summary>
/// <param name="predicate"></param>
/// <param name="pageNumber"></param>
/// <param name="pageSize"></param>
/// <returns></returns>
public IEnumerable<Airline> List(Expression<Func<Airline, bool>> predicate, int pageNumber, int pageSize)
{
IEnumerable<Airline> results;
if (predicate == null)
{
results = _context.Airlines;
results = results.Skip((pageNumber - 1) * pageSize)
.Take(pageSize);
}
else
{
results = _context.Airlines
.Where(predicate)
.Skip((pageNumber - 1) * pageSize)
.Take(pageSize);
}

return results;
}

/// <summary>
/// Return all entities matching the specified criteria
/// </summary>
Expand All @@ -93,26 +56,6 @@ public IAsyncEnumerable<Airline> ListAsync(Expression<Func<Airline, bool>> predi
return results;
}

/// <summary>
/// Add a named airline, if it doesn't already exist
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public Airline Add(string name)
{
name = name.CleanString();
Airline airline = Get(a => a.Name == name);

if (airline == null)
{
airline = new Airline { Name = name };
_context.Airlines.Add(airline);
_context.SaveChanges();
}

return airline;
}

/// <summary>
/// Add a named airline, if it doesn't already exist
/// </summary>
Expand Down
Loading

0 comments on commit e0d6dda

Please sign in to comment.