Skip to content

Commit

Permalink
Sonar Warnings for Dot Net 9 for AB#16872 (#6393)
Browse files Browse the repository at this point in the history
* Fix sonar warnnigs for AccountDataAccess for AB#16872.

* Fix sonar warnings for PatientDataAccess for AB#16872.

* Limit sonar analysis to Apps folder only for AB#16872.

* Suppress CA1515, IDE0290 and IDE0160 warnings for AB#16872.

* Fix sonar warnings for Clinical Document for AB#16872.

* Fix sonar warnings for Common Data for AB#16872.

* Fix sonar warnings for Common UI for AB#16872.

* Fix sonar warnings for Database for AB#16872.

* Fix sonar warnings for DB Maintainer for AB#16872.

* Fix sonar warnings for Encounter for AB#16872.

* Fix sonar warnings for Gateway Api for AB#16872.

* Fix sonar warnings for Immunization for AB#16872.

* Fix sonar warnings for Job Scheduler for AB#16872.

* Fix sonar warnings for Laboratory for AB#16872.

* Fix sonar warnings for Medication for AB#16872.

* Fix sonar warnings for Patient for AB#16872.

* Fix sonar warnings for Common for AB#16872.

* Fix sonar warnings for Admin for AB#16872.

* Fix sonar warnings for Web Client for AB#16872.

* Update suppress message in Immunization for AB#16872.

* Move suppress message in Patient Data Access for AB#16872.

* Renamed methods in Patient for AB#16872.

* Fix sonar warnings in Obervability for AB#16872.

* Fix Rider warnings for AB#16872.

* Fix sonar warning fix for Swagger for AB#16872.
  • Loading branch information
BrianMaki authored Jan 8, 2025
1 parent a8a269d commit 25a46ee
Show file tree
Hide file tree
Showing 215 changed files with 1,367 additions and 1,471 deletions.
9 changes: 9 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,15 @@ indent_size = 2
# All Rules are enabled with default severity.
# Rules with IsEnabledByDefault = false are force-enabled with default severity.

# CA1515 Suppress "Because an application's API isn't typically referenced from outside the assembly, types can be made internal"
dotnet_diagnostic.ca1515.severity = none

# IDE0290 Suppress "Use primary constructor"
dotnet_diagnostic.IDE0290.severity = none

# IDE0160 Suppress "Convert to block scoped namespace"
dotnet_diagnostic.IDE0160.severity = none

# S101: Types should be named in PascalCase
dotnet_diagnostic.s101.severity = none

Expand Down
16 changes: 3 additions & 13 deletions Apps/AccountDataAccess/src/Audit/AuditRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,9 @@ namespace HealthGateway.AccountDataAccess.Audit
/// <summary>
/// Handle audit data.
/// </summary>
public class AuditRepository : IAuditRepository
/// <param name="agentAuditDelegate">The injected agent audit delegate.</param>
public class AuditRepository(IAgentAuditDelegate agentAuditDelegate) : IAuditRepository
{
private readonly IAgentAuditDelegate agentAuditDelegate;

/// <summary>
/// Initializes a new instance of the <see cref="AuditRepository"/> class.
/// </summary>
/// <param name="agentAuditDelegate">The injected agent audit delegate.</param>
public AuditRepository(IAgentAuditDelegate agentAuditDelegate)
{
this.agentAuditDelegate = agentAuditDelegate;
}

private static ActivitySource ActivitySource { get; } = new(typeof(AuditRepository).FullName);

/// <inheritdoc/>
Expand All @@ -50,7 +40,7 @@ public async Task<IEnumerable<AgentAudit>> HandleAsync(AgentAuditQuery query, Ca
activity?.AddBaggage("AuditGroup", query.Group.ToString());
}

return await this.agentAuditDelegate.GetAgentAuditsAsync(query.Hdid, query.Group, ct);
return await agentAuditDelegate.GetAgentAuditsAsync(query.Hdid, query.Group, ct);
}
}
}
3 changes: 1 addition & 2 deletions Apps/AccountDataAccess/src/Patient/Address.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
namespace HealthGateway.AccountDataAccess.Patient
{
using System.Collections.Generic;
using System.Linq;

/// <summary>
/// Represents an address.
Expand All @@ -26,7 +25,7 @@ public class Address
/// <summary>
/// Gets or sets the street lines.
/// </summary>
public IEnumerable<string> StreetLines { get; set; } = Enumerable.Empty<string>();
public IEnumerable<string> StreetLines { get; set; } = [];

/// <summary>
/// Gets or sets the city name.
Expand Down
100 changes: 45 additions & 55 deletions Apps/AccountDataAccess/src/Patient/ClientRegistriesDelegate.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,11 @@ namespace HealthGateway.AccountDataAccess.Patient
/// <summary>
/// The Client Registries delegate.
/// </summary>
internal class ClientRegistriesDelegate : IClientRegistriesDelegate
/// <param name="logger">The injected logger provider.</param>
/// <param name="clientRegistriesClient">The injected client registries soap client.</param>
internal class ClientRegistriesDelegate(
ILogger<ClientRegistriesDelegate> logger,
QUPA_AR101102_PortType clientRegistriesClient) : IClientRegistriesDelegate
{
private const string Instance = "INSTANCE";
private static readonly List<string> WarningResponseCodes =
Expand All @@ -41,23 +45,6 @@ internal class ClientRegistriesDelegate : IClientRegistriesDelegate
"BCHCIM.GD.1.0022", "BCHCIM.GD.0.0023", "BCHCIM.GD.1.0023", "BCHCIM.GD.0.0578", "BCHCIM.GD.1.0578",
];

private readonly QUPA_AR101102_PortType clientRegistriesClient;
private readonly ILogger<ClientRegistriesDelegate> logger;

/// <summary>
/// Initializes a new instance of the <see cref="ClientRegistriesDelegate"/> class.
/// Constructor that requires an IEndpointBehavior for dependency injection.
/// </summary>
/// <param name="logger">The injected logger provider.</param>
/// <param name="clientRegistriesClient">The injected client registries soap client.</param>
public ClientRegistriesDelegate(
ILogger<ClientRegistriesDelegate> logger,
QUPA_AR101102_PortType clientRegistriesClient)
{
this.logger = logger;
this.clientRegistriesClient = clientRegistriesClient;
}

private static ActivitySource ActivitySource { get; } = new(typeof(ClientRegistriesDelegate).FullName);

/// <inheritdoc/>
Expand All @@ -66,13 +53,13 @@ public async Task<PatientModel> GetDemographicsAsync(OidType type, string identi
using Activity? activity = ActivitySource.StartActivity();
activity?.AddBaggage("PatientIdentifier", identifier);

this.logger.LogDebug("Retrieving patient from the Client Registry");
logger.LogDebug("Retrieving patient from the Client Registry");

// Create request object
HCIM_IN_GetDemographicsRequest request = CreateRequest(type, identifier);

// Perform the request
HCIM_IN_GetDemographicsResponse1 reply = await this.clientRegistriesClient.HCIM_IN_GetDemographicsAsync(request);
HCIM_IN_GetDemographicsResponse1 reply = await clientRegistriesClient.HCIM_IN_GetDemographicsAsync(request);
return this.ParseResponse(reply);
}

Expand Down Expand Up @@ -162,7 +149,32 @@ private static HCIM_IN_GetDemographicsRequest CreateRequest(OidType oidType, str
return new HCIM_IN_GetDemographicsRequest(request);
}

private static Address? MapAddress(AD? address)
private static Name ExtractName(PN nameSection)
{
// Extract the subject names
List<string> givenNameList = [];
List<string> lastNameList = [];
foreach (ENXP name in nameSection.Items)
{
if (name.GetType() == typeof(engiven) && (name.qualifier == null || !name.qualifier.Contains(cs_EntityNamePartQualifier.CL)))
{
givenNameList.Add(name.Text[0]);
}
else if (name.GetType() == typeof(enfamily) && (name.qualifier == null || !name.qualifier.Contains(cs_EntityNamePartQualifier.CL)))
{
lastNameList.Add(name.Text[0]);
}
}

const string delimiter = " ";
return new Name
{
GivenName = givenNameList.Aggregate((i, j) => i + delimiter + j),
Surname = lastNameList.Aggregate((i, j) => i + delimiter + j),
};
}

private Address? MapAddress(AD? address)
{
if (address?.Items == null)
{
Expand All @@ -189,37 +201,15 @@ private static HCIM_IN_GetDemographicsRequest CreateRequest(OidType oidType, str
case ADCountry country:
retAddress.Country = country.Text[0] ?? string.Empty;
break;
default:
logger.LogDebug("Unmatched item of type {Type}", item.GetType());
break;
}
}

return retAddress;
}

private static Name ExtractName(PN nameSection)
{
// Extract the subject names
List<string> givenNameList = [];
List<string> lastNameList = [];
foreach (ENXP name in nameSection.Items)
{
if (name.GetType() == typeof(engiven) && (name.qualifier == null || !name.qualifier.Contains(cs_EntityNamePartQualifier.CL)))
{
givenNameList.Add(name.Text[0]);
}
else if (name.GetType() == typeof(enfamily) && (name.qualifier == null || !name.qualifier.Contains(cs_EntityNamePartQualifier.CL)))
{
lastNameList.Add(name.Text[0]);
}
}

const string delimiter = " ";
return new Name
{
GivenName = givenNameList.Aggregate((i, j) => i + delimiter + j),
Surname = lastNameList.Aggregate((i, j) => i + delimiter + j),
};
}

private void CheckResponseCode(string responseCode)
{
if (responseCode.Contains("BCHCIM.GD.2.0018", StringComparison.InvariantCulture))
Expand All @@ -229,7 +219,7 @@ private void CheckResponseCode(string responseCode)

if (responseCode.Contains("BCHCIM.GD.2.0006", StringComparison.InvariantCulture))
{
this.logger.LogWarning(ErrorMessages.PhnInvalid);
logger.LogWarning(ErrorMessages.PhnInvalid);
throw new ValidationException(ErrorMessages.PhnInvalid, [new("PHN", ErrorMessages.PhnInvalid)]); // should throw InvalidDataException instead
}

Expand All @@ -241,7 +231,7 @@ private void CheckResponseCode(string responseCode)
// Verify that the reply contains a result
if (!responseCode.Contains("BCHCIM.GD.0.0013", StringComparison.InvariantCulture))
{
this.logger.LogWarning(ErrorMessages.ClientRegistryDoesNotReturnPerson);
logger.LogWarning(ErrorMessages.ClientRegistryDoesNotReturnPerson);
throw new NotFoundException(ErrorMessages.ClientRegistryDoesNotReturnPerson);
}
}
Expand All @@ -261,7 +251,7 @@ private PatientModel ParseResponse(HCIM_IN_GetDemographicsResponse1 reply)
string? dobStr = retrievedPerson.identifiedPerson.birthTime.value;
if (!DateTime.TryParseExact(dobStr, "yyyyMMdd", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime dob))
{
this.logger.LogWarning("Unable to parse patient's date of birth");
logger.LogWarning("Unable to parse patient's date of birth");
throw new NotFoundException(ErrorMessages.InvalidServicesCard);
}

Expand All @@ -288,8 +278,8 @@ private PatientModel ParseResponse(HCIM_IN_GetDemographicsResponse1 reply)
AD[] addresses = retrievedPerson.addr;
if (addresses != null)
{
patientModel.PhysicalAddress = MapAddress(addresses.FirstOrDefault(a => a.use.Any(u => u == cs_PostalAddressUse.PHYS)));
patientModel.PostalAddress = MapAddress(addresses.FirstOrDefault(a => a.use.Any(u => u == cs_PostalAddressUse.PST)));
patientModel.PhysicalAddress = this.MapAddress(addresses.FirstOrDefault(a => a.use.Any(u => u == cs_PostalAddressUse.PHYS)));
patientModel.PostalAddress = this.MapAddress(addresses.FirstOrDefault(a => a.use.Any(u => u == cs_PostalAddressUse.PST)));
}

if (WarningResponseCodes.Any(code => responseCode.Contains(code, StringComparison.InvariantCulture)))
Expand All @@ -309,11 +299,11 @@ private void PopulateNames(HCIM_IN_GetDemographicsResponseIdentifiedPerson retri

if (documentedName == null && legalName == null)
{
this.logger.LogWarning("The Client Registry returned a person without a Documented Name or a Legal Name");
logger.LogWarning("The Client Registry returned a person without a Documented Name or a Legal Name");
}
else if (documentedName == null)
{
this.logger.LogWarning("The Client Registry returned a person without a Documented Name");
logger.LogWarning("The Client Registry returned a person without a Documented Name");
}

if (documentedName != null)
Expand All @@ -333,7 +323,7 @@ private void PopulateIdentifiers(HCIM_IN_GetDemographicsResponseIdentifiedPerson
II? identifiedPersonId = retrievedPerson.identifiedPerson?.id?.FirstOrDefault(x => x.root == OidType.Phn.ToString());
if (identifiedPersonId == null)
{
this.logger.LogWarning("The Client Registry returned a person without a PHN");
logger.LogWarning("The Client Registry returned a person without a PHN");
}
else
{
Expand All @@ -343,7 +333,7 @@ private void PopulateIdentifiers(HCIM_IN_GetDemographicsResponseIdentifiedPerson
II? subjectId = retrievedPerson.id?.FirstOrDefault(x => x.displayable && x.root == OidType.Hdid.ToString());
if (subjectId == null)
{
this.logger.LogWarning("The Client Registry returned a person without an HDID");
logger.LogWarning("The Client Registry returned a person without an HDID");
}
else
{
Expand Down
8 changes: 4 additions & 4 deletions Apps/AccountDataAccess/src/Patient/PatientMappings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public PatientMappings()
private static Name ExtractPreferredName(PatientIdentity patientIdentity)
{
string preferredName = StringManipulator.JoinWithoutBlanks(
new[] { patientIdentity.PreferredFirstName, patientIdentity.PreferredSecondName, patientIdentity.PreferredThirdName });
[patientIdentity.PreferredFirstName, patientIdentity.PreferredSecondName, patientIdentity.PreferredThirdName]);

return new()
{
Expand All @@ -50,7 +50,7 @@ private static Name ExtractPreferredName(PatientIdentity patientIdentity)
private static Name ExtractLegalName(PatientIdentity patientIdentity)
{
string legalName = StringManipulator.JoinWithoutBlanks(
new[] { patientIdentity.LegalFirstName, patientIdentity.LegalSecondName, patientIdentity.LegalThirdName });
[patientIdentity.LegalFirstName, patientIdentity.LegalSecondName, patientIdentity.LegalThirdName]);

return new()
{
Expand All @@ -64,7 +64,7 @@ private static Name ExtractLegalName(PatientIdentity patientIdentity)
if (ShouldReturnHomeAddress(patientIdentity))
{
IEnumerable<string> streetLines = StringManipulator.ExcludeBlanks(
new[] { patientIdentity.HomeAddressStreetOne, patientIdentity.HomeAddressStreetTwo, patientIdentity.HomeAddressStreetThree });
[patientIdentity.HomeAddressStreetOne, patientIdentity.HomeAddressStreetTwo, patientIdentity.HomeAddressStreetThree]);

return new()
{
Expand All @@ -84,7 +84,7 @@ private static Name ExtractLegalName(PatientIdentity patientIdentity)
if (ShouldReturnPostalAddress(patientIdentity))
{
IEnumerable<string> streetLines = StringManipulator.ExcludeBlanks(
new[] { patientIdentity.MailAddressStreetOne, patientIdentity.MailAddressStreetTwo, patientIdentity.MailAddressStreetThree });
[patientIdentity.MailAddressStreetOne, patientIdentity.MailAddressStreetTwo, patientIdentity.MailAddressStreetThree]);

return new()
{
Expand Down
19 changes: 8 additions & 11 deletions Apps/AccountDataAccess/src/Patient/PatientRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,11 @@ private static string GetStrategy(string? hdid, PatientDetailSource source)

private async Task<PatientQueryResult> HandlePatientDetailsQueryAsync(PatientDetailsQuery query, CancellationToken ct)
{
if (ct.IsCancellationRequested)
{
throw new InvalidOperationException("Cancellation was requested");
}

using Activity? activity = ActivitySource.StartActivity();

if (!string.IsNullOrEmpty(query.Hdid))
Expand All @@ -206,17 +211,9 @@ private async Task<PatientQueryResult> HandlePatientDetailsQueryAsync(PatientDet

this.logger.LogDebug("Retrieving patient details");

if (ct.IsCancellationRequested)
{
throw new InvalidOperationException("Cancellation was requested");
}

if (query.Hdid == null && query.Phn == null)
{
throw new InvalidOperationException("Must specify either Hdid or Phn to query patient details");
}

return await this.GetPatientAsync(query, ct: ct);
return (query.Hdid ?? query.Phn) == null
? throw new InvalidOperationException("Must specify either Hdid or Phn to query patient details")
: await this.GetPatientAsync(query, ct: ct);
}

private async Task<PatientQueryResult> GetPatientAsync(PatientDetailsQuery query, bool disabledValidation = false, CancellationToken ct = default)
Expand Down
47 changes: 16 additions & 31 deletions Apps/AccountDataAccess/src/Patient/Strategy/HdidAllStrategy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,43 +31,28 @@ namespace HealthGateway.AccountDataAccess.Patient.Strategy
/// <summary>
/// Strategy implementation for all hdid patient data sources with or without cache.
/// </summary>
internal class HdidAllStrategy : PatientQueryStrategy
/// <param name="configuration">The injected configuration.</param>
/// <param name="cacheProvider">The injected cache provider.</param>
/// <param name="logger">The injected logger.</param>
/// <param name="clientRegistriesDelegate">The injected client registries delegate.</param>
/// <param name="patientIdentityApi">The injected patient identity api.</param>
/// <param name="mapper">The injected mapper.</param>
internal class HdidAllStrategy(
IConfiguration configuration,
ICacheProvider cacheProvider,
IClientRegistriesDelegate clientRegistriesDelegate,
IPatientIdentityApi patientIdentityApi,
ILogger<HdidAllStrategy> logger,
IMapper mapper) : PatientQueryStrategy(configuration, cacheProvider, logger)
{
private readonly IClientRegistriesDelegate clientRegistriesDelegate;
private readonly IPatientIdentityApi patientIdentityApi;
private readonly IMapper mapper;

/// <summary>
/// Initializes a new instance of the <see cref="HdidAllStrategy"/> class.
/// </summary>
/// <param name="configuration">The injected configuration.</param>
/// <param name="cacheProvider">The injected cache provider.</param>
/// <param name="logger">The injected logger.</param>
/// <param name="clientRegistriesDelegate">The injected client registries delegate.</param>
/// <param name="patientIdentityApi">The injected patient identity api.</param>
/// <param name="mapper">The injected mapper.</param>
public HdidAllStrategy(
IConfiguration configuration,
ICacheProvider cacheProvider,
IClientRegistriesDelegate clientRegistriesDelegate,
IPatientIdentityApi patientIdentityApi,
ILogger<HdidAllStrategy> logger,
IMapper mapper)
: base(configuration, cacheProvider, logger)
{
this.clientRegistriesDelegate = clientRegistriesDelegate;
this.patientIdentityApi = patientIdentityApi;
this.mapper = mapper;
}

/// <inheritdoc/>
public override async Task<PatientModel> GetPatientAsync(PatientRequest request, CancellationToken ct = default)
{
PatientModel? patient = request.UseCache ? await this.GetFromCacheAsync(request.Identifier, PatientIdentifierType.Hdid, ct) : null;

try
{
patient ??= await this.clientRegistriesDelegate.GetDemographicsAsync(OidType.Hdid, request.Identifier, request.DisabledValidation, ct);
patient ??= await clientRegistriesDelegate.GetDemographicsAsync(OidType.Hdid, request.Identifier, request.DisabledValidation, ct);
}
catch (CommunicationException ce)
{
Expand All @@ -76,8 +61,8 @@ public override async Task<PatientModel> GetPatientAsync(PatientRequest request,
try
{
this.GetLogger().LogDebug("Retrieving patient from PHSA");
PatientIdentity result = await this.patientIdentityApi.GetPatientIdentityAsync(request.Identifier, ct);
patient = this.mapper.Map<PatientModel>(result);
PatientIdentity result = await patientIdentityApi.GetPatientIdentityAsync(request.Identifier, ct);
patient = mapper.Map<PatientModel>(result);
}
catch (ApiException e) when (e.StatusCode == HttpStatusCode.NotFound)
{
Expand Down
Loading

0 comments on commit 25a46ee

Please sign in to comment.