Skip to content

Commit

Permalink
feat: implement device entity and his repository and use case
Browse files Browse the repository at this point in the history
  • Loading branch information
leynier committed May 16, 2022
1 parent efbc2ab commit 6701668
Show file tree
Hide file tree
Showing 17 changed files with 195 additions and 19 deletions.
16 changes: 16 additions & 0 deletions Gateways.Api/Controllers/DevicesController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using AutoMapper;
using Gateways.Api.Models;
using Gateways.Business.Contracts.Entities;
using Gateways.Business.Contracts.UseCases;
using Gateways.Common.Controllers;
using Microsoft.EntityFrameworkCore;

namespace Gateways.Api.Controllers;

public class DevicesController : CrudApiControllerBase<Device, DeviceGetModel, DeviceGetDetailsModel, DevicePostModel, DevicePutModel, int>
{
public DevicesController(IDeviceUseCase useCase, IMapper mapper)
: base(useCase, mapper, q => q.Include(d => d.Gateway))
{
}
}
8 changes: 5 additions & 3 deletions Gateways.Api/Controllers/GatewaysController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@
using Gateways.Business.Contracts.Entities;
using Gateways.Business.Contracts.UseCases;
using Gateways.Common.Controllers;
using Microsoft.EntityFrameworkCore;

namespace Gateways.Api.Controllers;

public class GatewaysController : CrudApiControllerBase<Gateway, GatewayGetModel, GatewayPostModel, GatewayPutModel>
public class GatewaysController : CrudApiControllerBase<Gateway, GatewayGetModel, GatewayGetDetailsModel, GatewayPostModel, GatewayPutModel, string>
{
public GatewaysController(IGatewayUseCase useCase, IMapper mapper) : base(useCase, mapper)
public GatewaysController(IGatewayUseCase useCase, IMapper mapper)
: base(useCase, mapper, q => q.Include(g => g.Devices))
{
}
}
}
16 changes: 16 additions & 0 deletions Gateways.Api/MapperProfiles/DeviceProfile.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using AutoMapper;
using Gateways.Api.Models;
using Gateways.Business.Contracts.Entities;

namespace Gateways.Api.MapperProfiles;

public class DeviceProfile : Profile
{
public DeviceProfile()
{
CreateMap<Device, DeviceGetModel>();
CreateMap<Device, DeviceGetDetailsModel>();
CreateMap<DevicePostModel, Device>();
CreateMap<DevicePutModel, Device>();
}
}
1 change: 1 addition & 0 deletions Gateways.Api/MapperProfiles/GatewayProfile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ public class GatewayProfile : Profile
public GatewayProfile()
{
CreateMap<Gateway, GatewayGetModel>();
CreateMap<Gateway, GatewayGetDetailsModel>();
CreateMap<GatewayPostModel, Gateway>();
CreateMap<GatewayPutModel, Gateway>();
}
Expand Down
37 changes: 37 additions & 0 deletions Gateways.Api/Models/DeviceModels.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using Gateways.Business.Contracts.Enums;
using System.ComponentModel.DataAnnotations;

namespace Gateways.Api.Models;

public class DeviceBaseModel
{
[Required]
public string Vendor { get; set; } = default!;
[Required]
public DateTime DateCreated { get; set; } = DateTime.UtcNow;
[Required]
public DeviceStatus Status { get; set; } = DeviceStatus.Offline;

[Required]
public string GatewayId { get; set; } = default!;
}

public class DeviceGetModel : DeviceBaseModel
{
public int Id { get; set; } = default!;
}

public class DeviceGetDetailsModel : DeviceGetModel
{
public GatewayGetModel Gateway { get; set; } = default!;
}

public class DevicePostModel : DeviceBaseModel
{

}

public class DevicePutModel : DeviceBaseModel
{

}
12 changes: 12 additions & 0 deletions Gateways.Api/Models/GatewayModels.cs
Original file line number Diff line number Diff line change
@@ -1,15 +1,27 @@
using Gateways.Common.Validators;
using System.ComponentModel.DataAnnotations;

namespace Gateways.Api.Models;

public class GatewayBaseModel
{
[Required]
public string Name { get; set; } = default!;
[Required]
[IPv4]
public string IPv4 { get; set; } = default!;
}

public class GatewayGetModel : GatewayBaseModel
{
public string Id { get; set; } = default!;
}

public class GatewayGetDetailsModel : GatewayGetModel
{
public IEnumerable<DeviceGetModel> Devices { get; set; } = new List<DeviceGetModel>();
}

public class GatewayPostModel : GatewayBaseModel
{

Expand Down
4 changes: 3 additions & 1 deletion Gateways.Business.Bootstrapper/Bootstrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,13 @@ public static void Boot(this IServiceCollection services, IConfiguration configu
});

services.AddScoped<IObjectContext, ObjectContext>();

// UseCases
services.AddScoped<IDeviceUseCase, DeviceUseCase>();
services.AddScoped<IGatewayUseCase, GatewayUseCase>();

// Repositories
services.AddScoped<IDeviceRepository, DeviceRepository>();
services.AddScoped<IGatewayRepository, GatewayRepository>();
}
}
Expand Down
18 changes: 18 additions & 0 deletions Gateways.Business.Contracts/Entities/Device.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using Gateways.Business.Contracts.Enums;
using System.ComponentModel.DataAnnotations;

namespace Gateways.Business.Contracts.Entities;

public class Device : Entity<int>
{
[Required]
public string Vendor { get; set; } = default!;
[Required]
public DateTime DateCreated { get; set; } = DateTime.UtcNow;
[Required]
public DeviceStatus Status { get; set; } = DeviceStatus.Offline;

[Required]
public string GatewayId { get; set; } = default!;
public Gateway Gateway { get; set; } = default!;
}
7 changes: 6 additions & 1 deletion Gateways.Business.Contracts/Entities/Gateway.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
namespace Gateways.Business.Contracts.Entities;
using System.ComponentModel.DataAnnotations;

namespace Gateways.Business.Contracts.Entities;

public class Gateway : Entity
{
[Required]
public string Name { get; set; } = default!;
[Required]
public string IPv4 { get; set; } = default!;
public IEnumerable<Device> Devices { get; set; } = new List<Device>();
}
7 changes: 7 additions & 0 deletions Gateways.Business.Contracts/Enums/DeviceStatus.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Gateways.Business.Contracts.Enums;

public enum DeviceStatus
{
Offline,
Online,
}
7 changes: 7 additions & 0 deletions Gateways.Business.Contracts/UseCases/IDeviceUseCase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
using Gateways.Business.Contracts.Entities;

namespace Gateways.Business.Contracts.UseCases;

public interface IDeviceUseCase : IUseCase<Device>
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using Gateways.Business.Contracts;
using Gateways.Business.Contracts.Entities;

namespace Gateways.Business.Implementations.Repositories;

public interface IDeviceRepository : IRepository<Device>
{
}
12 changes: 12 additions & 0 deletions Gateways.Business.Implementations/UseCases/DeviceUseCase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using Gateways.Business.Contracts.Entities;
using Gateways.Business.Contracts.UseCases;
using Gateways.Business.Implementations.Repositories;

namespace Gateways.Business.Implementations.UseCases;

public class DeviceUseCase : BaseUseCase<Device>, IDeviceUseCase
{
public DeviceUseCase(IDeviceRepository repository) : base(repository)
{
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ public class GatewayUseCase : BaseUseCase<Gateway>, IGatewayUseCase
{
public GatewayUseCase(IGatewayRepository repository) : base(repository)
{

}
}
34 changes: 20 additions & 14 deletions Gateways.Common/Controllers/CrudApiControllerBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,22 @@

namespace Gateways.Common.Controllers;

public class CrudApiControllerBase<TEntity, TGet, TPost, TPut> : ApiControllerBase where TEntity : Entity
public class CrudApiControllerBase<TEntity, TGet, TGetDetails, TPost, TPut, TKey> : ApiControllerBase where TEntity : Entity<TKey>
{
private readonly IUseCase<TEntity> useCase;
private readonly Func<IQueryable<TEntity>, IQueryable<TEntity>>? includer;
protected readonly IUseCase<TEntity> useCase;

public CrudApiControllerBase(IUseCase<TEntity> useCase, IMapper mapper) : base(mapper)
public CrudApiControllerBase(
IUseCase<TEntity> useCase,
IMapper mapper,
Func<IQueryable<TEntity>, IQueryable<TEntity>>? includer = null) : base(mapper)
{
this.includer = includer;
this.useCase = useCase;
}

[HttpGet]
public Response<IEnumerable<TGet>> GetAll()
public virtual Response<IEnumerable<TGet>> GetAll()
{
var models = useCase
.AsNoTrackingWithIdentityResolution()
Expand All @@ -27,18 +32,19 @@ public Response<IEnumerable<TGet>> GetAll()
}

[HttpGet("{id}")]
public Response<TGet> Get(string id)
public virtual Response<TGetDetails> Get(TKey id)
{
var model = useCase
.AsNoTrackingWithIdentityResolution()
.FirstOrDefault(g => g.Id == id);
IQueryable<TEntity> query = useCase.AsNoTrackingWithIdentityResolution();
if (includer != null)
query = includer(query);
var model = query.FirstOrDefault(g => Equals(g.Id, id));
if (model == null)
throw new NotFoundError();
return OkResponse<TGet>(model);
return OkResponse<TGetDetails>(model);
}

[HttpPost]
public Response<TGet> Post([FromBody] TPost model)
public virtual Response<TGet> Post([FromBody] TPost model)
{
var entity = mapper.Map<TEntity>(model);
useCase.Add(entity);
Expand All @@ -47,9 +53,9 @@ public Response<TGet> Post([FromBody] TPost model)
}

[HttpPut("{id}")]
public Response<TGet> Put(string id, [FromBody] TPut model)
public virtual Response<TGet> Put(TKey id, [FromBody] TPut model)
{
var entity = useCase.FirstOrDefault(g => g.Id == id);
var entity = useCase.FirstOrDefault(g => Equals(g.Id, id));
if (entity == null)
throw new NotFoundError();
mapper.Map(model, entity);
Expand All @@ -58,9 +64,9 @@ public Response<TGet> Put(string id, [FromBody] TPut model)
}

[HttpDelete("{id}")]
public Response<TGet> Delete(string id)
public virtual Response<TGet> Delete(TKey id)
{
var entity = useCase.FirstOrDefault(g => g.Id == id);
var entity = useCase.FirstOrDefault(g => Equals(g.Id, id));
if (entity == null)
throw new NotFoundError();
useCase.Remove(entity);
Expand Down
13 changes: 13 additions & 0 deletions Gateways.Data.Implementations/ObjectContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,14 @@ namespace Gateways.Data.Implementations;

public class ObjectContext : DbContext, IObjectContext
{
#region Constructors

public ObjectContext(DbContextOptions<ObjectContext> options) : base(options) { }

#endregion

#region Methods and Properties

IQueryable<TEntity> IObjectContext.Query<TEntity>() => Set<TEntity>();

void IObjectContext.Add<TEntity>(TEntity entity) => Set<TEntity>().Add(entity);
Expand All @@ -20,5 +26,12 @@ public ObjectContext(DbContextOptions<ObjectContext> options) : base(options) {

Task IObjectContext.CommitAsync() => SaveChangesAsync();

#endregion

#region DbSets

public DbSet<Device> Devices { get; set; } = default!;
public DbSet<Gateway> Gateways { get; set; } = default!;

#endregion
}
13 changes: 13 additions & 0 deletions Gateways.Data.Implementations/Repositories/DeviceRepository.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using Gateways.Business.Contracts;
using Gateways.Business.Contracts.Entities;
using Gateways.Business.Implementations.Repositories;

namespace Gateways.Data.Implementations.Repositories
{
public class DeviceRepository : BaseRepository<Device, int>, IDeviceRepository
{
public DeviceRepository(IObjectContext context) : base(context)
{
}
}
}

0 comments on commit 6701668

Please sign in to comment.