Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public interface IQueryPlanQueries
Task<List<QueryPlanModel>> FindAsync(Expression<Func<QueryPlan, bool>> predicate, CancellationToken cancellationToken = default);
Task<List<string>> GetPlanNamesAsync(string facilityId, CancellationToken cancellationToken = default);
Task<PagedConfigModel<QueryPlanModel>> SearchAsync(SearchQueryPlanModel model, CancellationToken cancellationToken = default);
Task<bool> ExistsAsync(string facilityId, Frequency value, CancellationToken cancellationToken);
}

public class QueryPlanQueries : IQueryPlanQueries
Expand Down Expand Up @@ -131,4 +132,9 @@ private Expression<Func<T, object>> SetSortBy<T>(string? sortBy)
var converted = Expression.Convert(property, typeof(object));
return Expression.Lambda<Func<T, object>>(converted, parameter);
}

public Task<bool> ExistsAsync(string facilityId, Frequency value, CancellationToken cancellationToken)
{
return _dbContext.QueryPlans.AnyAsync(q => q.FacilityId == facilityId && q.Type == value);
}
Comment thread
nvmLantana marked this conversation as resolved.
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
using LantanaGroup.Link.DataAcquisition.Domain.Infrastructure.Interfaces;
using LantanaGroup.Link.DataAcquisition.Domain.Infrastructure.Models.QueryConfig;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace LantanaGroup.Link.DataAcquisition.Domain.Application.Serializers;

public class QueryPlanConverter : JsonConverter<IQueryConfig>
{
public override IQueryConfig Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
using (JsonDocument doc = JsonDocument.ParseValue(ref reader))
{
JsonElement typeElement;
string configType = null;

if (doc.RootElement.TryGetProperty("QueryConfigType", out typeElement) ||
doc.RootElement.TryGetProperty("queryConfigType", out typeElement))
{
configType = typeElement.GetString();
}
else if (doc.RootElement.TryGetProperty("$type", out typeElement))
{
var typeName = typeElement.GetString();
if (typeName?.Contains("ParameterQueryConfig") == true)
{
configType = "Parameter";
}
else if (typeName?.Contains("ReferenceQueryConfig") == true)
{
configType = "Reference";
}
}

if (configType == null)
{
// Fallback to property inspection if no type discriminator is found
if (doc.RootElement.TryGetProperty("Parameters", out _))
{
configType = "Parameter";
}
else if (doc.RootElement.TryGetProperty("Paged", out _))
{
configType = "Reference";
}
else
{
throw new JsonException("Unable to determine QueryConfigType. Missing type discriminator or distinguishing properties.");
}
}

return configType switch
{
"Parameter" => JsonSerializer.Deserialize<ParameterQueryConfig>(doc.RootElement.GetRawText(), options),
"Reference" => JsonSerializer.Deserialize<ReferenceQueryConfig>(doc.RootElement.GetRawText(), options),
_ => throw new JsonException($"Unknown QueryConfigType: {configType}")
};
}
}

public override void Write(Utf8JsonWriter writer, IQueryConfig value, JsonSerializerOptions options)
{
JsonSerializer.Serialize(writer, value, value.GetType(), options);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
entity.Property(e => e.Id).ValueGeneratedOnAdd();

var jsonOptions = new JsonSerializerOptions();
jsonOptions.Converters.Add(new QueryConfigConverter());
jsonOptions.Converters.Add(new QueryPlanConverter());
jsonOptions.Converters.Add(new ParameterConverter());
jsonOptions.Converters.Add(new JsonStringEnumConverter());

Expand Down
16 changes: 9 additions & 7 deletions DotNet/DataAcquisition/Controllers/QueryPlanConfigController.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using DataAcquisition.Domain.Application.Models;
using DataAcquisition.Domain.Application.Models.Exceptions;
using Hl7.Fhir.Model;
using LantanaGroup.Link.DataAcquisition.Domain.Application.Managers;
using LantanaGroup.Link.DataAcquisition.Domain.Application.Models;
using LantanaGroup.Link.DataAcquisition.Domain.Application.Models.Exceptions;
Expand Down Expand Up @@ -139,9 +140,9 @@ public async Task<IActionResult> CreateQueryPlan(

if (ModelState.IsValid)
{
var existing = await _queryPlanQueries.GetAsync(facilityId, queryPlan.Type.Value, cancellationToken);
var exists = await _queryPlanQueries.ExistsAsync(facilityId, queryPlan.Type.Value, cancellationToken);

if (existing != null)
if (exists)
{
throw new EntityAlreadyExistsException($"A Query Plan already exists for facilityId: {facilityId}.");
}
Expand Down Expand Up @@ -254,9 +255,9 @@ public async Task<ActionResult> UpdateQueryPlan(

if (ModelState.IsValid)
{
var existing = await _queryPlanQueries.GetAsync(facilityId, queryPlan.Type.Value, cancellationToken);
var exists = await _queryPlanQueries.ExistsAsync(facilityId, queryPlan.Type.Value, cancellationToken);

if (existing == null)
if (!exists)
{
throw new NotFoundException($"A Query Plan was not found for facilityId: {facilityId}.");
}
Expand Down Expand Up @@ -340,6 +341,7 @@ public async Task<ActionResult> DeleteQueryPlan(

try
{
facilityId = facilityId.SanitizeAndRemove();
if (string.IsNullOrWhiteSpace(facilityId))
{
throw new BadRequestException("parameter facilityId is required.");
Expand All @@ -350,14 +352,14 @@ public async Task<ActionResult> DeleteQueryPlan(
throw new BadRequestException("type query parameter must be defined.");
}

var existing = await _queryPlanQueries.GetAsync(facilityId.Sanitize(), parameters.Type.Value, cancellationToken);
var exists = await _queryPlanQueries.ExistsAsync(facilityId, parameters.Type.Value, cancellationToken);

if (existing == null)
if (!exists)
{
throw new NotFoundException($"A QueryPlan or Query component was not found for facilityId: {facilityId}.");
}

await _queryPlanManager.DeleteAsync(facilityId.Sanitize(), parameters.Type.Value, cancellationToken);
await _queryPlanManager.DeleteAsync(facilityId, parameters.Type.Value, cancellationToken);

return Accepted();
}
Expand Down
2 changes: 1 addition & 1 deletion DotNet/DataAcquisition/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ static void RegisterServices(WebApplicationBuilder builder)
options.JsonSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
options.JsonSerializerOptions.PropertyNameCaseInsensitive = true;
options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
options.JsonSerializerOptions.Converters.Add(new QueryConfigConverter());
options.JsonSerializerOptions.Converters.Add(new QueryPlanConverter());
options.JsonSerializerOptions.Converters.Add(new ParameterConverter());
options.JsonSerializerOptions.Converters.Add(new TimeSpanConverter());
options.JsonSerializerOptions.ForFhir(ModelInfo.ModelInspector);
Expand Down
Loading