-
Notifications
You must be signed in to change notification settings - Fork 50
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2222 from jaroslavbliznak/feature/184_Batch_updat…
…e_mnemonics FIX-184 Batch update of mnemonics
- Loading branch information
Showing
19 changed files
with
783 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.ComponentModel; | ||
using System.Linq; | ||
|
||
namespace Witsml.Helpers; | ||
|
||
/// <summary> | ||
/// Helper class for working with Enum. | ||
/// </summary> | ||
public static class EnumHelper | ||
{ | ||
/// <summary> | ||
/// Gets a list of descriptions for all values in the specified Enum. | ||
/// </summary> | ||
/// <typeparam name="TEnum">The Enum type.</typeparam> | ||
/// <returns>A list of string descriptions for all Enum values.</returns> | ||
public static List<string> GetEnumDescriptions<TEnum>() where TEnum : Enum | ||
{ | ||
return Enum.GetValues(typeof(TEnum)) | ||
.Cast<TEnum>() | ||
.Select(value => GetEnumDescription(value)) | ||
.ToList(); | ||
} | ||
|
||
/// <summary> | ||
/// Gets the description of a specific Enum value. If the description is not found, then return the enum value. | ||
/// </summary> | ||
/// <param name="value">The Enum value.</param> | ||
/// <typeparam name="TEnum">The Enum type.</typeparam> | ||
/// <returns>The description of the Enum value.</returns> | ||
public static string GetEnumDescription<TEnum>(TEnum value) | ||
where TEnum : Enum | ||
{ | ||
var field = typeof(TEnum).GetField(value.ToString()); | ||
return field != null && | ||
Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) | ||
is DescriptionAttribute descriptionAttribute | ||
? descriptionAttribute.Description | ||
: value.ToString(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
|
||
using WitsmlExplorer.Api.Jobs.Common; | ||
using WitsmlExplorer.Api.Models; | ||
|
||
namespace WitsmlExplorer.Api.Jobs | ||
{ | ||
/// <summary> | ||
/// Job for batch modification of logCurveInfo. | ||
/// </summary> | ||
public record BatchModifyLogCurveInfoJob : Job | ||
{ | ||
/// <summary> | ||
/// WellboreReference API model. | ||
/// </summary> | ||
public WellboreReference WellboreReference { get; init; } | ||
|
||
/// <summary> | ||
/// Edited logCurveInfo API model. | ||
/// </summary> | ||
public LogCurveInfo EditedLogCurveInfo { get; init; } | ||
|
||
/// <summary> | ||
/// Collection of logCurveInfos and log Uids API models. | ||
/// </summary> | ||
public ICollection<LogCurveInfoBatchItem> LogCurveInfoBatchItems | ||
{ | ||
get; | ||
init; | ||
} | ||
|
||
/// <summary> | ||
/// Getting a description of batch-modified LogCurveInfos. | ||
/// </summary> | ||
/// <returns></returns> | ||
public override string Description() | ||
{ | ||
return $"To Batch Modify - Uids: {string.Join(", ", LogCurveInfoBatchItems.Select(batchItem => batchItem.LogCurveInfoUid))}"; | ||
} | ||
|
||
/// <summary> | ||
/// Getting name of logCurveInfo. | ||
/// </summary> | ||
/// <returns>null</returns> | ||
public override string GetObjectName() | ||
{ | ||
return null; | ||
} | ||
|
||
/// <summary> | ||
/// Getting name of wellbore. | ||
/// </summary> | ||
/// <returns>String of wellbore name.</returns> | ||
public override string GetWellboreName() | ||
{ | ||
return WellboreReference.WellboreName; | ||
} | ||
|
||
/// <summary> | ||
/// Getting name of well. | ||
/// </summary> | ||
/// <returns>String of well name.</returns> | ||
public override string GetWellName() | ||
{ | ||
return WellboreReference.WellName; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
using System.ComponentModel; | ||
|
||
namespace WitsmlExplorer.Api.Models; | ||
|
||
public enum LogTraceState | ||
{ | ||
[Description("depth adjusted")] | ||
DepthAdjusted, | ||
|
||
[Description("edited")] | ||
Edited, | ||
|
||
[Description("joined")] | ||
Joined, | ||
|
||
[Description("processed")] | ||
Processed, | ||
|
||
[Description("raw")] | ||
Raw, | ||
|
||
[Description("unknown")] | ||
Unknown | ||
} |
19 changes: 19 additions & 0 deletions
19
Src/WitsmlExplorer.Api/Models/Reports/BatchModifyLogCurveInfoReport.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
namespace WitsmlExplorer.Api.Models.Reports; | ||
|
||
/// <summary> | ||
/// Batch modification report for logCurveInfos. | ||
/// </summary> | ||
public class BatchModifyLogCurveInfoReport : BaseReport | ||
{ | ||
} | ||
|
||
/// <summary> | ||
/// The item information about a batch modification is extended with LogUid. | ||
/// </summary> | ||
public class BatchModifyLogCurveInfoReportItem : BatchModifyReportItem | ||
{ | ||
/// <summary> | ||
/// Log unique identifier. | ||
/// </summary> | ||
public string LogUid { get; init; } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
153 changes: 153 additions & 0 deletions
153
Src/WitsmlExplorer.Api/Workers/Modify/BatchModifyLogCurveInfoWorker.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,153 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Threading.Tasks; | ||
|
||
using Microsoft.Extensions.Logging; | ||
|
||
using Witsml; | ||
using Witsml.Data; | ||
using Witsml.Data.Measures; | ||
using Witsml.Helpers; | ||
using Witsml.ServiceReference; | ||
|
||
using WitsmlExplorer.Api.Jobs; | ||
using WitsmlExplorer.Api.Models; | ||
using WitsmlExplorer.Api.Models.Reports; | ||
using WitsmlExplorer.Api.Services; | ||
|
||
namespace WitsmlExplorer.Api.Workers.Modify; | ||
|
||
/// <summary> | ||
/// Worker for batch modification of LogCurveInfo. | ||
/// </summary> | ||
public class BatchModifyLogCurveInfoWorker : BaseWorker<BatchModifyLogCurveInfoJob>, IWorker | ||
{ | ||
public JobType JobType => JobType.BatchModifyLogCurveInfo; | ||
|
||
public BatchModifyLogCurveInfoWorker(ILogger<BatchModifyLogCurveInfoJob> logger, IWitsmlClientProvider witsmlClientProvider) : base(witsmlClientProvider, logger) { } | ||
|
||
/// <summary> | ||
/// Executes a batch modification job for LogCurveInfoItem properties. | ||
/// </summary> | ||
/// <param name="job">The job model contains batch modification parameters for logCurveInfo.</param> | ||
/// <returns>Task of the worker Result in a report with a result of batch modification.</returns> | ||
public override async Task<(WorkerResult, RefreshAction)> Execute(BatchModifyLogCurveInfoJob job) | ||
{ | ||
Verify(job); | ||
|
||
Logger.LogInformation("Started {JobType}. {jobDescription}", JobType, job.Description()); | ||
|
||
WitsmlLogs logHeaders = await GetLogHeaders(job.WellboreReference.WellUid, job.WellboreReference.WellboreUid, job.LogCurveInfoBatchItems.Select(x => x.LogUid).Distinct().ToArray()); | ||
|
||
IList<(string logUid, WitsmlLogCurveInfo logCurveInfo)> originalLogCurveInfoData = job.LogCurveInfoBatchItems | ||
.SelectMany(batchItem => | ||
{ | ||
WitsmlLog logHeader = logHeaders.Logs.Find(l => l.Uid == batchItem.LogUid); | ||
var curveInfo = logHeader?.LogCurveInfo.FirstOrDefault(c => c.Uid == batchItem.LogCurveInfoUid); | ||
return curveInfo != null ? new[] { (logHeader.Uid, curveInfo) } : Array.Empty<(string, WitsmlLogCurveInfo)>(); | ||
}) | ||
.ToList(); | ||
|
||
IList<WitsmlLogs> logCurveInfosToUpdateQueries = originalLogCurveInfoData | ||
.Select(obj => GetModifyLogCurveInfoQuery(job, obj)).ToList(); | ||
List<QueryResult> modifyResults = logCurveInfosToUpdateQueries | ||
.Select(async query => await GetTargetWitsmlClientOrThrow().UpdateInStoreAsync(query)) | ||
.Select(updateTask => updateTask.Result).ToList(); | ||
|
||
var report = CreateReport(job, originalLogCurveInfoData, modifyResults); | ||
job.JobInfo.Report = report; | ||
|
||
if (modifyResults.Any(result => !result.IsSuccessful)) | ||
{ | ||
string errorMessage = $"Failed to modify some LogCurveInfos"; | ||
var reason = "Inspect the report for details"; | ||
Logger.LogError("{ErrorMessage}. {jobDescription}", errorMessage, job.Description()); | ||
return (new WorkerResult(GetTargetWitsmlClientOrThrow().GetServerHostname(), false, errorMessage, reason, null, job.JobInfo.Id), null); | ||
} | ||
|
||
Logger.LogInformation("{JobType} - Job successful", GetType().Name); | ||
WorkerResult workerResult = new(GetTargetWitsmlClientOrThrow().GetServerHostname(), true, $"The LogCurveInfo properties have been updated in the batch.", jobId: job.JobInfo.Id); | ||
RefreshObjects refreshAction = new(GetTargetWitsmlClientOrThrow().GetServerHostname(), job.WellboreReference.WellUid, job.WellboreReference.WellboreUid, EntityType.Log); | ||
return (workerResult, refreshAction); | ||
} | ||
|
||
private BatchModifyLogCurveInfoReport CreateReport(BatchModifyLogCurveInfoJob job, IList<(string logUid, WitsmlLogCurveInfo logCurveInfo)> logCurveInfoData, IList<QueryResult> results) | ||
{ | ||
var reportItems = logCurveInfoData.Select((obj, index) => new BatchModifyLogCurveInfoReportItem | ||
{ | ||
WellUid = job.WellboreReference.WellUid, | ||
WellboreUid = job.WellboreReference.WellboreUid, | ||
LogUid = obj.logUid, | ||
Uid = obj.logCurveInfo.Uid, | ||
IsSuccessful = results[index].IsSuccessful ? CommonConstants.Yes : CommonConstants.No, | ||
FailureReason = results[index].IsSuccessful ? string.Empty : results[index].Reason | ||
}).ToList(); | ||
|
||
return new BatchModifyLogCurveInfoReport() | ||
{ | ||
Title = "Batch Update LogCurveInfo Report", | ||
Summary = $"Updated {logCurveInfoData.Count} objects", | ||
WarningMessage = results.Any(result => !result.IsSuccessful) ? "Some logCurveInfos were not modified. Inspect the reasons below." : null, | ||
ReportItems = reportItems | ||
}; | ||
} | ||
|
||
private WitsmlLogs GetModifyLogCurveInfoQuery(BatchModifyLogCurveInfoJob job, (string logUid, WitsmlLogCurveInfo logCurveInfo) originalLogCurveInfoData) | ||
{ | ||
if (!string.IsNullOrEmpty(job.EditedLogCurveInfo.TraceState)) | ||
{ | ||
originalLogCurveInfoData.logCurveInfo.TraceState = job.EditedLogCurveInfo.TraceState; | ||
} | ||
|
||
originalLogCurveInfoData.logCurveInfo.SensorOffset = job.EditedLogCurveInfo.SensorOffset?.ToWitsml<WitsmlLengthMeasure>(); | ||
|
||
if (!string.IsNullOrEmpty(job.EditedLogCurveInfo.NullValue)) | ||
{ | ||
originalLogCurveInfoData.logCurveInfo.NullValue = job.EditedLogCurveInfo.NullValue; | ||
} | ||
|
||
return new() | ||
{ | ||
Logs = new List<WitsmlLog> | ||
{ | ||
new() | ||
{ | ||
UidWell = job.WellboreReference.WellUid, | ||
UidWellbore = job.WellboreReference.WellboreUid, | ||
Uid = originalLogCurveInfoData.logUid, | ||
LogCurveInfo = new List<WitsmlLogCurveInfo>() | ||
{ | ||
originalLogCurveInfoData.logCurveInfo | ||
} | ||
} | ||
} | ||
}; | ||
} | ||
|
||
private async Task<WitsmlLogs> GetLogHeaders(string wellUid, string wellboreUid, string[] logUids) | ||
{ | ||
return await LogWorkerTools.GetLogsByIds(GetTargetWitsmlClientOrThrow(), wellUid, wellboreUid, logUids, ReturnElements.HeaderOnly); | ||
} | ||
|
||
private void Verify(BatchModifyLogCurveInfoJob job) | ||
{ | ||
if (!job.LogCurveInfoBatchItems.Any()) | ||
{ | ||
throw new InvalidOperationException("LogCurveInfoBatchItems must be specified"); | ||
} | ||
|
||
if (string.IsNullOrEmpty(job.WellboreReference.WellUid)) | ||
{ | ||
throw new InvalidOperationException("WellUid cannot be empty"); | ||
} | ||
|
||
if (string.IsNullOrEmpty(job.WellboreReference.WellboreUid)) | ||
{ | ||
throw new InvalidOperationException("WellboreUid cannot be empty"); | ||
} | ||
|
||
ModifyUtils.VerifyMeasure(job.EditedLogCurveInfo.SensorOffset, nameof(job.EditedLogCurveInfo.SensorOffset)); | ||
ModifyUtils.VerifyAllowedValues(job.EditedLogCurveInfo.TraceState, EnumHelper.GetEnumDescriptions<LogTraceState>(), nameof(job.EditedLogCurveInfo.TraceState)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.