Skip to content

Commit

Permalink
Support the Attachment object💡 #2616 (#2622)
Browse files Browse the repository at this point in the history
  • Loading branch information
robertbasti authored Dec 9, 2024
1 parent 11637a9 commit df1ef90
Show file tree
Hide file tree
Showing 12 changed files with 328 additions and 0 deletions.
50 changes: 50 additions & 0 deletions Src/Witsml/Data/WitsmlAttachment.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using System.Collections.Generic;
using System.Xml.Serialization;

using Witsml.Data.Measures;
using Witsml.Extensions;

namespace Witsml.Data
{
public class WitsmlAttachment : WitsmlObjectOnWellbore
{
public override WitsmlAttachments AsItemInWitsmlList()
{
return new WitsmlAttachments()
{
Attachments = this.AsItemInList()
};
}

[XmlElement("objectReference")]
public WitsmlObjectReference ObjectReference { get; set; }

[XmlElement("subObjectReference")]
public WitsmlObjectReference SubObjectReference { get; set; }

[XmlElement("md")]
public WitsmlMeasuredDepthCoord Md { get; set; }

[XmlElement("mdBit")]
public WitsmlMeasuredDepthCoord MdBit { get; set; }

[XmlElement("param")]
public List<WitsmlIndexedObject> Param { get; set; }

[XmlElement("fileName")]
public string FileName { get; set; }

[XmlElement("description")]
public string Description { get; set; }

[XmlElement("fileType")]
public string FileType { get; set; }

[XmlElement("content")]
public string Content { get; set; }

[XmlElement("commonData")]
public WitsmlCommonData CommonData { get; set; }

}
}
25 changes: 25 additions & 0 deletions Src/Witsml/Data/WitsmlAttachments.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using System.Collections.Generic;
using System.Linq;
using System.Xml.Serialization;

namespace Witsml.Data
{
[XmlRoot("attachments", Namespace = "http://www.witsml.org/schemas/1series")]
public class WitsmlAttachments : IWitsmlObjectList
{
[XmlAttribute("version")]
public string Version = "1.4.1.1";

[XmlElement("attachment")]
public List<WitsmlAttachment> Attachments { get; set; } = new();

public string TypeName => "attachment";

[XmlIgnore]
public IEnumerable<WitsmlObjectOnWellbore> Objects
{
get => Attachments;
set => Attachments = value.Select(obj => (WitsmlAttachment)obj).ToList();
}
}
}
26 changes: 26 additions & 0 deletions Src/WitsmlExplorer.Api/HttpHandlers/AttachmentHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using System.Collections.Generic;
using System.Threading.Tasks;

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;

using WitsmlExplorer.Api.Models;
using WitsmlExplorer.Api.Services;

namespace WitsmlExplorer.Api.HttpHandlers
{
public static class AttachmentHandler
{
[Produces(typeof(IEnumerable<Attachment>))]
public static async Task<IResult> GetAttachments(string wellUid, string wellboreUid, IAttachmentService attachmentService)
{
return TypedResults.Ok(await attachmentService.GetAttachments(wellUid, wellboreUid));

}
[Produces(typeof(Attachment))]
public static async Task<IResult> GetAttachment(string wellUid, string wellboreUid, string attachmentUid, IAttachmentService attachmentService)
{
return TypedResults.Ok(await attachmentService.GetAttachment(wellUid, wellboreUid, attachmentUid));
}
}
}
30 changes: 30 additions & 0 deletions Src/WitsmlExplorer.Api/Models/Attachment.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using Witsml.Data;

namespace WitsmlExplorer.Api.Models
{
public class Attachment : ObjectOnWellbore
{
public string FileName { get; set; }
public string Description { get; set; }
public string FileType { get; set; }
public string Content { get; set; }
public CommonData CommonData { get; set; }
public override WitsmlAttachments ToWitsml()
{
return new WitsmlAttachment
{
UidWell = WellUid,
NameWell = WellName,
UidWellbore = WellboreUid,
NameWellbore = WellboreName,
Uid = Uid,
Name = Name,
FileName = FileName,
Description = Description,
FileType = FileType,
Content = Content,
CommonData = CommonData?.ToWitsml()
}.AsItemInWitsmlList();
}
}
}
4 changes: 4 additions & 0 deletions Src/WitsmlExplorer.Api/Models/EntityType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public enum EntityType
Tubular,
Trajectory,
WbGeometry,
Attachment
}

public static class EntityTypeHelper
Expand Down Expand Up @@ -62,6 +63,7 @@ public static WitsmlObjectOnWellbore ToObjectOnWellbore(EntityType type)
EntityType.WbGeometry => new WitsmlWbGeometry(),
EntityType.Well => null,
EntityType.Wellbore => null,
EntityType.Attachment => new WitsmlAttachment(),
_ => null,
};
}
Expand Down Expand Up @@ -92,6 +94,7 @@ public static IWitsmlObjectList ToObjectList(EntityType type)
EntityType.WbGeometry => new WitsmlWbGeometrys(),
EntityType.Well => null,
EntityType.Wellbore => null,
EntityType.Attachment => new WitsmlAttachments(),
_ => null,
};
}
Expand All @@ -113,6 +116,7 @@ public static Type GetApiTypeFromEntityType(EntityType type)
EntityType.WbGeometry => typeof(WbGeometry),
EntityType.Well => typeof(Well),
EntityType.Wellbore => typeof(Wellbore),
EntityType.Attachment => typeof(Attachment),
_ => null,
};
}
Expand Down
51 changes: 51 additions & 0 deletions Src/WitsmlExplorer.Api/Query/AttachmentQueries.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
using Witsml.Data;
using Witsml.Extensions;

namespace WitsmlExplorer.Api.Query
{
public static class AttachmentQueries
{
public static WitsmlAttachments GetWitsmlAttachment(string wellUid, string wellboreUid, string attachmentUid = "")
{
return new WitsmlAttachments
{
Attachments = new WitsmlAttachment
{
Uid = attachmentUid,
UidWell = wellUid,
UidWellbore = wellboreUid,
NameWell = "",
NameWellbore = "",
Name = "",
FileName = "",
Description = "",
FileType = "",
Content = "",
CommonData = new WitsmlCommonData()
{
ItemState = "",
SourceName = "",
DTimLastChange = "",
DTimCreation = "",
ServiceCategory = "",
Comments = "",
DefaultDatum = "",
}
}.AsItemInList()
};
}

public static WitsmlAttachments QueryById(string wellUid, string wellboreUid, string attachmentUid)
{
return new WitsmlAttachments()
{
Attachments = new WitsmlAttachment
{
Uid = attachmentUid,
UidWell = wellUid,
UidWellbore = wellboreUid
}.AsItemInList()
};
}
}
}
3 changes: 3 additions & 0 deletions Src/WitsmlExplorer.Api/Routes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ public static void ConfigureApi(this WebApplication app, IConfiguration configur
app.MapGet(routes[EntityType.BhaRun], BhaRunHandler.GetBhaRuns, useOAuth2);
app.MapGet(routes[EntityType.BhaRun] + "/{bhaRunUid}", BhaRunHandler.GetBhaRun, useOAuth2);

app.MapGet(routes[EntityType.Attachment], AttachmentHandler.GetAttachments, useOAuth2);
app.MapGet(routes[EntityType.Attachment] + "/{attachmentUid}", AttachmentHandler.GetAttachment, useOAuth2);

app.MapGet("/wells/{wellUid}/wellbores/{wellboreUid}/changelogs", ChangeLogHandler.GetChangeLogs, useOAuth2);

app.MapGet(routes[EntityType.FluidsReport], FluidsReportHandler.GetFluidsReports, useOAuth2);
Expand Down
63 changes: 63 additions & 0 deletions Src/WitsmlExplorer.Api/Services/AttachmentService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

using Witsml.Data;
using Witsml.ServiceReference;

using WitsmlExplorer.Api.Models;
using WitsmlExplorer.Api.Query;

namespace WitsmlExplorer.Api.Services
{
public interface IAttachmentService
{
Task<Attachment> GetAttachment(string wellUid, string wellboreUid, string attachmentUid);
Task<ICollection<Attachment>> GetAttachments(string wellUid, string wellboreUid);
}

public class AttachmentService : WitsmlService, IAttachmentService
{
public AttachmentService(IWitsmlClientProvider witsmlClientProvider) : base(witsmlClientProvider) { }

public async Task<Attachment> GetAttachment(string wellUid, string wellboreUid, string attachmentUid)
{
WitsmlAttachments query = AttachmentQueries.GetWitsmlAttachment(wellUid, wellboreUid, attachmentUid);
WitsmlAttachments result = await _witsmlClient.GetFromStoreAsync(query, new OptionsIn(ReturnElements.All));
return WitsmlToAttachment(result.Attachments.FirstOrDefault());
}
public async Task<ICollection<Attachment>> GetAttachments(string wellUid, string wellboreUid)
{
WitsmlAttachments witsmlAttachments = AttachmentQueries.GetWitsmlAttachment(wellUid, wellboreUid);
WitsmlAttachments result = await _witsmlClient.GetFromStoreAsync(witsmlAttachments, new OptionsIn(ReturnElements.Requested));
return result.Attachments.Select(WitsmlToAttachment).OrderBy(attachment => attachment.Name).ToList();
}

private static Attachment WitsmlToAttachment(WitsmlAttachment attachment)
{
return attachment == null ? null : new Attachment
{
Uid = attachment.Uid,
Name = attachment.Name,
WellUid = attachment.UidWell,
WellName = attachment.NameWell,
WellboreName = attachment.NameWellbore,
WellboreUid = attachment.UidWellbore,
FileName = attachment.FileName,
Description = attachment.Description,
FileType = attachment.FileType,
Content = attachment.Content,
CommonData = new CommonData()
{
ItemState = attachment.CommonData.ItemState,
SourceName = attachment.CommonData.SourceName,
DTimLastChange = attachment.CommonData.DTimLastChange,
DTimCreation = attachment.CommonData.DTimCreation,
ServiceCategory = attachment.CommonData.ServiceCategory,
Comments = attachment.CommonData.Comments,
DefaultDatum = attachment.CommonData.DefaultDatum,
}
};
}
}
}
11 changes: 11 additions & 0 deletions Src/WitsmlExplorer.Api/Workers/Modify/ModifyUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,17 @@ public static void VerifyAllowedValues(string value, List<string> allowedValues,
nameof(WbGeometry.CommonData)
}
},
{
EntityType.Attachment, new HashSet<string>
{
nameof(Attachment.Name),
nameof(Attachment.FileName),
nameof(Attachment.Description),
nameof(Attachment.FileType),
nameof(Attachment.Content),
nameof(Attachment.CommonData)
}
},
};

public static void VerifyModificationProperties(ObjectOnWellbore obj, EntityType objectType, ILogger logger)
Expand Down
3 changes: 3 additions & 0 deletions Tests/WitsmlExplorer.Api.Tests/Models/EntityTypeTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public void EntityTypeToPluralLowercase_Get_CorrectResult()
Assert.Equal("trajectories", strings[EntityType.Trajectory]);
Assert.Equal("tubulars", strings[EntityType.Tubular]);
Assert.Equal("wbgeometries", strings[EntityType.WbGeometry]);
Assert.Equal("attachments", strings[EntityType.Attachment]);
}

[Fact]
Expand All @@ -40,6 +41,7 @@ public void EntityTypeToObjectOnWellbore_GetAllWellboreObjects_CorrectType()
Assert.IsType<WitsmlTrajectory>(EntityTypeHelper.ToObjectOnWellbore(EntityType.Trajectory));
Assert.IsType<WitsmlTubular>(EntityTypeHelper.ToObjectOnWellbore(EntityType.Tubular));
Assert.IsType<WitsmlWbGeometry>(EntityTypeHelper.ToObjectOnWellbore(EntityType.WbGeometry));
Assert.IsType<WitsmlAttachment>(EntityTypeHelper.ToObjectOnWellbore(EntityType.Attachment));
}

[Fact]
Expand All @@ -54,6 +56,7 @@ public void EntityTypeToObjectList_GetAllWellboreObjectLists_CorrectType()
Assert.IsType<WitsmlTrajectories>(EntityTypeHelper.ToObjectList(EntityType.Trajectory));
Assert.IsType<WitsmlTubulars>(EntityTypeHelper.ToObjectList(EntityType.Tubular));
Assert.IsType<WitsmlWbGeometrys>(EntityTypeHelper.ToObjectList(EntityType.WbGeometry));
Assert.IsType<WitsmlAttachments>(EntityTypeHelper.ToObjectList(EntityType.Attachment));
}
}
}
18 changes: 18 additions & 0 deletions Tests/WitsmlExplorer.IntegrationTests/Resources/attachment.xml

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using System.Threading.Tasks;

using Witsml;
using Witsml.Data;
using Witsml.ServiceReference;
using Witsml.Xml;

using WitsmlExplorer.Api.Query;

using Xunit;

namespace WitsmlExplorer.IntegrationTests.Witsml.GetFromStore
{
public partial class AttachmentTests
{
private readonly WitsmlClient _client;

public AttachmentTests()
{
WitsmlConfiguration config = ConfigurationReader.GetWitsmlConfiguration();
_client = new WitsmlClient(options =>
{
options.Hostname = config.Hostname;
options.Credentials = new WitsmlCredentials(config.Username, config.Password);
});
}

[Fact(Skip = "Should only be run manually")]
public async Task GetAttachmentSerializesCorrectly()
{
// if the following attachment does not exit, add the file attachment to the server manually
// this affects wellUid, wellboreUid, nameWell, and nameWellbore values during comparison so adjust them here and in the file accordingly
string wellUid = "8c77de13-4fad-4b2e-ba3d-7e6b0e35a394";
string wellboreUid = "ae75db48-5cef-4bd1-9ddf-6035b0d2cd49";
string attachmentUid = "attachmentUid";
WitsmlAttachments queryExisting = AttachmentQueries.GetWitsmlAttachment(wellUid, wellboreUid, attachmentUid);
WitsmlAttachments serverAttachment = await _client.GetFromStoreAsync(queryExisting, new OptionsIn(ReturnElements.All));
string responseXml = XmlHelper.Serialize(serverAttachment);
string serverAttachmentXml = TestUtils.CleanResponse(responseXml);
string fileAttachmentXml = TestUtils.GetTestXml("Attachment");
Assert.Equal(fileAttachmentXml, serverAttachmentXml);
}
}
}

0 comments on commit df1ef90

Please sign in to comment.