docs(iec62304): [REL-1.0.2] validate and curate XML doc review markers

This commit is contained in:
n8n IEC 62304 Bot
2026-07-06 18:35:52 +02:00
parent 8e55c4a7c9
commit a67a9f5443
2 changed files with 92 additions and 0 deletions
@@ -20,6 +20,7 @@ namespace adas_core.Infrastructure.Repositories;
/// options lists, diagnoses, allergies, procedures, treatments, and other reference data.
/// </summary>
/// <typeparam name="T">The type of MasterList entity to manage.</typeparam>
/// <!-- aidoc:v1 sig=f958de2 -->
public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository<T> where T : MasterList
{
private readonly ApiSettings _apiSettings;
@@ -30,6 +31,7 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
/// <param name="apiSettings">API settings containing collection names configuration.</param>
/// <param name="database">The MongoDB database instance.</param>
/// <exception cref="ArgumentNullException">Thrown when apiSettings is null.</exception>
/// <!-- aidoc:v1 sig=800d538 body=d2b18a3 -->
public MasterListRepository(IOptions<ApiSettings> apiSettings, IMongoDatabase database) : base(database)
{
if (apiSettings == null) throw new ArgumentNullException(nameof(apiSettings));
@@ -41,6 +43,7 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
/// Maps different MasterList subtypes to their corresponding MongoDB collection names.
/// </summary>
/// <returns>The collection name for the current MasterList type.</returns>
/// <!-- aidoc:v1 sig=94e22ff body=64e6c55 -->
public override string GetCollectionName()
{
return typeof(T) switch
@@ -76,6 +79,7 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
/// </summary>
/// <param name="entity">The entity to insert.</param>
/// <exception cref="Exception">Throws and re-throws exceptions after logging.</exception>
/// <!-- aidoc:v1 sig=c7a7ad8 body=26b3581 -->
public override async Task InsertOneAsync(T entity)
{
try
@@ -94,6 +98,7 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
/// </summary>
/// <param name="id">The ObjectId of the entity to delete.</param>
/// <exception cref="Exception">Throws and re-throws exceptions after logging.</exception>
/// <!-- aidoc:v1 sig=3de1ad6 body=fe0ba8c -->
public async Task Delete(ObjectId id)
{
try
@@ -113,6 +118,10 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
/// </summary>
/// <param name="entity">The entity with updated values.</param>
/// <exception cref="Exception">Throws and re-throws exceptions after logging.</exception>
/// <!-- aidoc-review:v1 severity=high kind=wrong_summary
/// "Summary says 'Updates an existing' entity, but IsUpsert = true means the method will also insert the document if it does not already exist, so 'existing' is contradicted by the code." -->
/// <!-- aidoc-review:v1 severity=high kind=stale_summary
/// "The phrase 'master list entity' is not supported by the code, which is generic over T and contains no reference to a master list; the term appears to be carried over from a different/specialized method." -->
public async Task Update(T entity)
{
try
@@ -133,6 +142,7 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
/// <param name="id">The ObjectId of the master list.</param>
/// <param name="newOpt">The OptionList with updated values.</param>
/// <returns>The updated OptionList if found; otherwise, null.</returns>
/// <!-- aidoc:v1 sig=64ca4dd body=a7714e6 -->
public async Task<OptionList?> UpdateFullMasterListOption(ObjectId id, OptionList newOpt)
{
var filter = Builders<T>.Filter.Where(o => o.Id == id && o.Options.Any(opt => opt.Id == newOpt.Id)
@@ -166,6 +176,12 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
/// <param name="id">The ObjectId of the entity to retrieve.</param>
/// <returns>The MasterList entity if found; otherwise, null.</returns>
/// <exception cref="Exception">Logs errors and returns null on failure.</exception>
/// <!-- aidoc-review:v1 severity=high kind=wrong_summary
/// "Summary says 'master list entity' but the method is generic on type T, not specifically MasterList." -->
/// <!-- aidoc-review:v1 severity=high kind=wrong_returns
/// "Returns tag says 'The MasterList entity' but the method returns Task<T?> for a generic type T." -->
/// <!-- aidoc-review:v1 severity=high kind=wrong_exception
/// "Documents <exception cref='Exception'> but the catch block swallows exceptions and returns null; the method does not throw." -->
public async Task<T?> FindById(ObjectId id)
{
try
@@ -197,6 +213,8 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
/// <param name="locale">The locale for translation.</param>
/// <returns>The OptionList with translated fields if found; otherwise, null.</returns>
/// <exception cref="Exception">Logs errors and returns null on failure.</exception>
/// <!-- aidoc-review:v1 severity=medium kind=extra_exception
/// "The method wraps its body in a try-catch that catches all Exception instances and returns null; no exception is ever thrown to the caller, so the <exception cref=\"Exception\"> tag is misleading." -->
public async Task<OptionList?> FindOptionItemById(ObjectId masterId, ObjectId optionId, LocaleEnum locale)
{
try
@@ -342,6 +360,7 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
/// <param name="optionId">The ObjectId of the option to retrieve.</param>
/// <returns>The OptionList if found; otherwise, null.</returns>
/// <exception cref="Exception">Logs errors and returns null on failure.</exception>
/// <!-- aidoc:v1 sig=ccc34cb body=71837cc -->
public async Task<OptionList?> FindOptionItemById(ObjectId masterId, ObjectId optionId)
{
try
@@ -374,6 +393,10 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
/// <param name="locale">Optional locale for translated option names.</param>
/// <returns>The MasterList entity with translated options if found; otherwise, null.</returns>
/// <exception cref="Exception">Logs errors and returns null on failure.</exception>
/// <!-- aidoc-review:v1 severity=medium kind=extra_exception
/// "The <exception cref=\"Exception\"/> tag indicates the method can throw Exception, but the body catches all Exception and returns null, so it never throws." -->
/// <!-- aidoc-review:v1 severity=medium kind=wrong_returns
/// "Returns Task<T?> generically, but the doc describes the return as 'The MasterList entity'. The actual generic type is not constrained to MasterList." -->
public async Task<T?> FindById(ObjectId id, LocaleEnum? locale)
{
try
@@ -556,6 +579,12 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
/// <param name="name">The name of the master list to retrieve.</param>
/// <returns>The MasterList entity if found; otherwise, null.</returns>
/// <exception cref="Exception">Logs errors and returns null on failure.</exception>
/// <!-- aidoc-review:v1 severity=high kind=wrong_summary
/// "Summary describes a 'master list entity' but the method is generic over type T and is not specific to master lists." -->
/// <!-- aidoc-review:v1 severity=high kind=wrong_returns
/// "Documents the return as 'The MasterList entity' but the method returns Task<T?> where T is a generic type parameter." -->
/// <!-- aidoc-review:v1 severity=high kind=wrong_exception
/// "The method's try/catch catches every Exception and returns null, so no Exception is propagated to callers; the <exception> tag misrepresents the behavior." -->
public async Task<T?> FindByName(string name)
{
try
@@ -584,6 +613,7 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
/// <param name="id">The ObjectId of the master list.</param>
/// <param name="textSearch">Optional text to search within options.</param>
/// <returns>A list of matching OptionList items.</returns>
/// <!-- aidoc:v1 sig=569d223 body=bb7f2c6 -->
public async Task<List<OptionList>> GetMasterListByIdAndTextSearchContaining(ObjectId id, string? textSearch)
{
return await GetOptionsByTextSearch(textSearch, id);
@@ -594,6 +624,10 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
/// </summary>
/// <param name="filter">The pagination and filtering parameters.</param>
/// <returns>A fluent queryable for MasterList results.</returns>
/// <!-- aidoc-review:v1 severity=high kind=wrong_summary
/// "The summary states the method 'retrieves paginated master lists', but the method does not perform any pagination (no Skip/Limit calls) and does not 'retrieve' results—it only builds a fluent query. The actual pagination would need to be applied by the caller on the returned IFindFluent." -->
/// <!-- aidoc-review:v1 severity=high kind=wrong_returns
/// "The returns description says 'A fluent queryable for MasterList results', but the method's return type is IFindFluent<T, T>—a generic fluent queryable, not specific to MasterList. The type parameter T is not constrained to MasterList." -->
public IFindFluent<T, T> GetPaginatedMasterList(PaginationFilter filter)
{
var filterBuilder = Builders<T>.Filter;
@@ -621,6 +655,8 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
/// <param name="filter">The pagination and filtering parameters.</param>
/// <param name="listId">The ObjectId of the master list.</param>
/// <returns>A list of filtered OptionList items.</returns>
/// <!-- aidoc-review:v1 severity=high kind=wrong_summary
/// "Summary states the method 'retrieves paginated options', but the code performs no pagination (no Skip/Take); only the filter's text is applied, and all matching options are returned via .ToList()." -->
public async Task<List<OptionList>> GetPaginatedOptions(PaginationFilter filter, ObjectId listId)
{
//TODO: LOCALE
@@ -646,6 +682,10 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
/// <param name="opt">The option element to add.</param>
/// <returns>The newly created OptionList if successful; otherwise, null if duplicate exists.</returns>
/// <exception cref="Exception">Logs errors and returns null on failure.</exception>
/// <!-- aidoc-review:v1 severity=medium kind=wrong_returns
/// "The <returns> description states null is returned 'if duplicate exists', but null is also returned when UpdateOneAsync's ModifiedCount == 0 (e.g., document not found) and when an exception is caught, not solely on duplicate." -->
/// <!-- aidoc-review:v1 severity=medium kind=wrong_exception
/// "<exception cref=\"Exception\"> describes logging and returning null, but the code catches the exception from UpdateOneAsync rather than letting it propagate. Other parts of the method (e.g., GetMasterListByIdAndSearchOptions, FindById) are not wrapped in try/catch and could throw unhandled exceptions." -->
public async Task<OptionList?> AddOptionToMasterList(ObjectId id, FilterOptionListElement opt)
{
var exist = await GetMasterListByIdAndSearchOptions(id, opt);
@@ -689,6 +729,8 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
/// </summary>
/// <returns>An enumerable of all MasterList entities.</returns>
/// <exception cref="Exception">Logs errors and returns empty list on failure.</exception>
/// <!-- aidoc-review:v1 severity=high kind=extra_exception
/// "The method catches all exceptions internally and returns an empty list; it does not throw Exception to callers, so the <exception cref=\"Exception\"/> tag is misleading." -->
public async Task<IEnumerable<T>> GetAll()
{
try
@@ -708,6 +750,10 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
/// </summary>
/// <returns>An enumerable of MasterListDto containing id, name, description, listType, and options count.</returns>
/// <exception cref="Exception">Logs errors and returns empty list on failure.</exception>
/// <!-- aidoc-review:v1 severity=high kind=wrong_exception
/// "The <exception cref=\"Exception\"> tag implies the method throws Exception, but the body catches all exceptions and returns an empty list — it never propagates." -->
/// <!-- aidoc-review:v1 severity=high kind=wrong_summary
/// "Summary says 'Retrieves all master list entities without options', which reads as filtering for entities that have no options, but the code uses FilterDefinition<T>.Empty (no filter) and returns all entities with Options reduced to a count." -->
public async Task<IEnumerable<MasterListDto>> GetAllWithoutOptions()
{
try
@@ -736,6 +782,8 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
/// </summary>
/// <returns>The total count of entities.</returns>
/// <exception cref="Exception">Logs errors and returns 0 on failure.</exception>
/// <!-- aidoc-review:v1 severity=high kind=extra_exception
/// "The method catches all exceptions internally and returns 0, so it does not propagate Exception to callers. The <exception cref=\"Exception\"/> tag is misleading." -->
public async Task<int> Count()
{
try
@@ -758,6 +806,7 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
/// <param name="filters">The filter criteria including text, name, description, and optionType.</param>
/// <returns>A list of matching OptionList items ordered by name.</returns>
/// <exception cref="Exception">Logs errors and returns empty list on failure.</exception>
/// <!-- aidoc:v1 sig=f6ee5be body=17d6a96 -->
public async Task<List<OptionList>> GetMasterListByIdAndSearchOptions(ObjectId id, FilterOptionListElement? filters)
{
try
@@ -973,6 +1022,7 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
/// <param name="locale">The locale for translation updates.</param>
/// <returns>The updated OptionList if successful; otherwise, null.</returns>
/// <exception cref="Exception">Logs errors and returns null on failure.</exception>
/// <!-- aidoc:v1 sig=e771f23 body=5520a4a -->
public async Task<OptionList?> UpdateMasterListOption(ObjectId id, OptionList newOpt, LocaleEnum locale)
{
// 1. Evitar duplicados
@@ -1073,6 +1123,7 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
/// <param name="newOpt">The OptionList with updated values.</param>
/// <returns>The updated OptionList if successful; otherwise, null.</returns>
/// <exception cref="Exception">Logs errors and returns null on failure.</exception>
/// <!-- aidoc:v1 sig=6def54c body=9554543 -->
public async Task<OptionList?> UpdateMasterListOption(ObjectId id, OptionList newOpt)
{
var master = await FindById(id);
@@ -1108,6 +1159,7 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
/// <param name="id">The ObjectId of the master list.</param>
/// <param name="deleteOptId">The ObjectId of the option to delete.</param>
/// <returns>True if the option was deleted; otherwise, false.</returns>
/// <!-- aidoc:v1 sig=e663f16 body=75627bc -->
public async Task<bool> DeleteMasterListOption(ObjectId id, ObjectId deleteOptId)
{
// Define el filtro para encontrar el documento por su _id
@@ -1132,6 +1184,8 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
/// <param name="opt">The UpdateMasterListDetailsDto with updated values.</param>
/// <returns>The updated UpdateMasterListDetailsDto if successful; otherwise, null.</returns>
/// <exception cref="Exception">Logs errors and returns null on failure.</exception>
/// <!-- aidoc-review:v1 severity=medium kind=extra_exception
/// "The method catches and handles Exception internally (returning null) rather than throwing it; the <exception cref=\"Exception\"> tag is therefore incorrect since no exception is propagated to the caller." -->
public async Task<UpdateMasterListDetailsDto?> UpdateOptionDetailsToMasterList(ObjectId id,
UpdateMasterListDetailsDto opt)
{
@@ -1167,6 +1221,8 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
/// <param name="name">The new name.</param>
/// <returns>True if the update was successful; otherwise, false.</returns>
/// <exception cref="Exception">Logs errors and returns false on failure.</exception>
/// <!-- aidoc-review:v1 severity=medium kind=extra_exception
/// "The method catches all exceptions in a try/catch and returns false; it never throws Exception to the caller, so the <exception cref=\"Exception\"> tag is incorrect." -->
public async Task<bool> UpdateMasterListName(ObjectId id, string name)
{
var filter = Builders<T>.Filter.And(
@@ -1193,6 +1249,8 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
/// <param name="description">The new description.</param>
/// <returns>True if the update was successful; otherwise, false.</returns>
/// <exception cref="Exception">Logs errors and returns false on failure.</exception>
/// <!-- aidoc-review:v1 severity=medium kind=extra_exception
/// "The <exception cref=\"Exception\"/> tag implies the method throws, but the catch block handles all exceptions internally and the method never rethrows; the tag is misleading and should be removed." -->
public async Task<bool> UpdateMasterListDescription(ObjectId id, string description)
{
var filter = Builders<T>.Filter.And(
@@ -1219,6 +1277,8 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
/// <param name="oldOpt">The OptionList to remove.</param>
/// <returns>True if the option was removed; otherwise, false.</returns>
/// <exception cref="Exception">Logs errors and returns false on failure.</exception>
/// <!-- aidoc-review:v1 severity=high kind=wrong_exception
/// "The method catches all Exception types and returns false; it does not throw Exception, so listing it as a thrown exception is misleading." -->
public async Task<bool> RemoveMasterListOption(ObjectId id, OptionList oldOpt)
{
var filter = Builders<T>.Filter.Eq("_id", id);
@@ -1250,6 +1310,8 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
/// Creates necessary indexes for the MasterList collection.
/// Currently creates text indexes for DiagnosisList on options.name, options.description, and options._id.
/// </summary>
/// <!-- aidoc-review:v1 severity=high kind=wrong_summary
/// "Documentation claims 'text indexes' are created, but the code uses Builders<T>.IndexKeys.Ascending(...), which creates regular ascending B-tree indexes, not text indexes." -->
public override async Task CreateIndexes()
{
if (typeof(T) == typeof(DiagnosisList))
@@ -1275,6 +1337,7 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
/// </summary>
/// <param name="textSearch">Optional text to search within options.</param>
/// <returns>A list of matching OptionList items.</returns>
/// <!-- aidoc:v1 sig=484b092 body=48e3496 -->
public async Task<List<OptionList>> GetMasterListByTextSearch(string? textSearch)
{
return await GetOptionsByTextSearch(textSearch);
@@ -1287,6 +1350,7 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
/// <param name="id">Optional master list ObjectId to filter results.</param>
/// <returns>A list of matching OptionList items ordered by name.</returns>
/// <exception cref="Exception">Logs errors and returns empty list on failure.</exception>
/// <!-- aidoc:v1 sig=6ebeac8 body=1d7bbb7 -->
private async Task<List<OptionList>> GetOptionsByTextSearch(string? textSearch, ObjectId? id = null)
{
try
@@ -1364,6 +1428,8 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
/// <param name="filters">List of filter definitions to apply.</param>
/// <param name="sort">Sort definition for the query results.</param>
/// <returns>A fluent queryable for T results.</returns>
/// <!-- aidoc-review:v1 severity=high kind=wrong_summary
/// "The summary states the method creates a query 'for paginated results', but the code contains no pagination logic (no Skip/Limit calls); it only applies a combined filter and sort before returning the IFindFluent." -->
private IFindFluent<T, T> CreateFindFluent(List<FilterDefinition<T>> filters, SortDefinition<T> sort)
{
var combinedFilter = filters.Any()
@@ -1379,6 +1445,8 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
/// <param name="localeList">The default locale to exclude from translations.</param>
/// <param name="opt">The option name to use as default translation.</param>
/// <returns>A Locale object with translations for all other locales.</returns>
/// <!-- aidoc-review:v1 severity=medium kind=wrong_summary
/// "Summary states 'Creates LocaleItem entries for all locales except the specified default' but the code also explicitly excludes the LocaleEnum.Default value in addition to the localeList parameter, so two locales are skipped, not one." -->
private Locale GetNewItemLocale(LocaleEnum localeList, string opt)
{
var newLocale = new Locale();
@@ -1418,6 +1486,7 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
/// </summary>
/// <param name="input">The input string to build the pattern from.</param>
/// <returns>A regex-compatible pattern string.</returns>
/// <!-- aidoc:v1 sig=2992c00 body=ae88daf -->
private static string BuildRegexPattern(string input)
{
var regexPattern = new StringBuilder();
@@ -1459,6 +1528,8 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
/// <param name="locale">The locale for translation.</param>
/// <returns>A list of matching OptionList items ordered by name.</returns>
/// <exception cref="Exception">Logs errors and returns empty list on failure.</exception>
/// <!-- aidoc-review:v1 severity=medium kind=extra_exception
/// "The method catches all exceptions internally (catch (Exception ex)) and returns an empty list; no exceptions are propagated, so documenting <exception cref=\"Exception\"> is misleading." -->
private async Task<List<OptionList>> GetMasterListByIdAndTextSearch(
ObjectId id, string newOptName, LocaleEnum locale)
{