Skip to content

Commit

Permalink
Merge branch 'develop' into feature/rename-code-terminology-service
Browse files Browse the repository at this point in the history
  • Loading branch information
mmsmits authored Mar 6, 2024
2 parents 76cd365 + c42b3d8 commit 9f4752a
Show file tree
Hide file tree
Showing 7 changed files with 77 additions and 32 deletions.
12 changes: 7 additions & 5 deletions src/Hl7.Fhir.Base/Rest/BaseFhirClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ namespace Hl7.Fhir.Rest
public partial class BaseFhirClient : IDisposable
{
internal readonly ModelInspector Inspector;
private readonly IFhirSerializationEngine _serializationEngine;
private readonly Lazy<List<HttpStatusCode>> _200responses = new(() => Enum.GetValues(typeof(HttpStatusCode)).Cast<HttpStatusCode>().Where(n => (int)n > 199 && (int)n < 300).ToList());

/// <summary>
Expand Down Expand Up @@ -78,8 +77,6 @@ internal BaseFhirClient(Uri endpoint, ModelInspector inspector, FhirClientSettin
Inspector = inspector;
Settings = settings;
Endpoint = getValidatedEndpoint(endpoint);
_serializationEngine = settings.SerializationEngine ??
FhirSerializationEngineFactory.Legacy.FromParserSettings(Inspector, settings.ParserSettings ?? new());

Requester = requester;

Expand Down Expand Up @@ -1069,7 +1066,7 @@ private static ResourceIdentity verifyResourceIdentity(Uri location, bool needId
var request = tx.Entry[0];
var requestMessage = request.ToHttpRequestMessage(
Requester.BaseUrl,
_serializationEngine,
getSerializationEngine(),
Settings.UseFhirVersionInAcceptHeader ? fhirVersion : null,
Settings);

Expand All @@ -1079,7 +1076,7 @@ private static ResourceIdentity verifyResourceIdentity(Uri location, bool needId
// of the server, add a suggestion about this in the (legacy) parsing exception.
var suggestedVersionOnParseError = !Settings.VerifyFhirVersion ? fhirVersion : null;
(LastResult, LastBody, LastBodyAsText, LastBodyAsResource, var issue) =
await ValidateResponse(responseMessage, expect, _serializationEngine, suggestedVersionOnParseError)
await ValidateResponse(responseMessage, expect, getSerializationEngine(), suggestedVersionOnParseError)
.ConfigureAwait(false);

// If an error occurred while trying to interpret and validate the response, we will bail out now.
Expand Down Expand Up @@ -1172,6 +1169,11 @@ private static bool isPostOrPutOrPatch(Bundle.EntryComponent interaction) =>

private bool _versionChecked = false;

private IFhirSerializationEngine getSerializationEngine()
{
return Settings.SerializationEngine ?? FhirSerializationEngineFactory.Legacy.FromParserSettings(Inspector, Settings.ParserSettings ?? new());
}

private async Task verifyServerVersion(CancellationToken ct)
{
if (!Settings.VerifyFhirVersion) return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ public static IFhirSerializationEngine BackwardsCompatible(ModelInspector inspec
/// and just continue parsing. Note that this may mean data loss.
/// </summary>
public static IFhirSerializationEngine Ostrich(ModelInspector inspector) =>
new PocoSerializationEngine(inspector, _ => true);
new PocoSerializationEngine(inspector, _ => true, new FhirJsonPocoDeserializerSettings(){Validator = null}, new FhirXmlPocoDeserializerSettings(){Validator = null});


private static bool isRecoverableIssue(CodedException ce) =>
Expand Down
27 changes: 12 additions & 15 deletions src/Hl7.Fhir.Base/Serialization/engine/PocoSerializationEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
using Hl7.Fhir.Utility;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;

namespace Hl7.Fhir.Serialization
Expand All @@ -27,39 +28,35 @@ internal class PocoSerializationEngine : IFhirSerializationEngine

private readonly ModelInspector _inspector;
private readonly Predicate<CodedException> _ignoreFilter;

/// <summary>
/// Creates an implementation of <see cref="IFhirSerializationEngine"/> that uses the newer POCO (de)serializers.
/// </summary>
/// <param name="inspector">Reflection data of the POCO model to use.</param>
/// <param name="ignoreFilter">A predicate that returns true for issues that should not be reported.</param>
public PocoSerializationEngine(ModelInspector inspector, Predicate<CodedException> ignoreFilter)
{
_inspector = inspector;
_ignoreFilter = ignoreFilter;
}
private readonly FhirJsonPocoDeserializerSettings _jsonSettings;
private readonly FhirXmlPocoDeserializerSettings _xmlSettings;

/// <summary>
/// Creates an implementation of <see cref="IFhirSerializationEngine"/> that uses the newer POCO (de)serializers.
/// </summary>
/// <param name="inspector">Reflection data of the POCO model to use.</param>
public PocoSerializationEngine(ModelInspector inspector)
/// <param name="ignoreFilter">Predicate specifying which exceptions to ignore</param>
/// <param name="jsonSettings">Settings for json deserializing</param>
/// <param name="xmlSettings">Settings for xml deserializing</param>
public PocoSerializationEngine(ModelInspector inspector, Predicate<CodedException>? ignoreFilter=null, FhirJsonPocoDeserializerSettings? jsonSettings=null, FhirXmlPocoDeserializerSettings? xmlSettings=null)
{
_inspector = inspector;
_ignoreFilter = _ => false;
_ignoreFilter = ignoreFilter ?? (_ => false);
_jsonSettings = jsonSettings ?? new FhirJsonPocoDeserializerSettings();
_xmlSettings = xmlSettings ?? new FhirXmlPocoDeserializerSettings();
}

/// <inheritdoc />
public Resource DeserializeFromXml(string data)
{
var deserializer = new BaseFhirXmlPocoDeserializer(_inspector);
var deserializer = new BaseFhirXmlPocoDeserializer(_inspector, _xmlSettings);
return deserializeAndIgnoreErrors(deserializer.TryDeserializeResource, data);
}

/// <inheritdoc />
public Resource DeserializeFromJson(string data)
{
var deserializer = new BaseFhirJsonPocoDeserializer(_inspector);
var deserializer = new BaseFhirJsonPocoDeserializer(_inspector, _jsonSettings);
return deserializeAndIgnoreErrors(deserializer.TryDeserializeResource, data);
}

Expand Down
25 changes: 16 additions & 9 deletions src/Hl7.Fhir.Base/Specification/Source/ZipCacher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
* available at /~https://github.com/FirelyTeam/firely-net-sdk/blob/master/LICENSE
*/

using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
Expand Down Expand Up @@ -67,11 +68,11 @@ public bool IsActual()

if (!dir.Exists) return false;

// Sometimes unzipping fails after creating the directory, try to fix that by
// checking if there are any files at all.
var dirIsEmpty = !dir.EnumerateFileSystemInfos().Any();
if (dirIsEmpty) return false;

// zip unpacking fails sometimes (issue #2164). if this cache is supposed to contain the specification, it should have at least a bunch of files in there (notably, we test for profiles-types.xml)
var isSpecificationZip = ZipPath.EndsWith(Path.Combine("specification.zip"));
var doesNotHaveCriticalFiles = !File.Exists(Path.Combine(CachePath, "specification", "profiles-types.xml"));
if (isSpecificationZip && doesNotHaveCriticalFiles) return false;
var currentZipFileTime = File.GetLastWriteTimeUtc(ZipPath);

return dir.CreationTimeUtc >= currentZipFileTime;
Expand Down Expand Up @@ -107,8 +108,14 @@ public void Refresh()

dir.Create();


ZipFile.ExtractToDirectory(ZipPath, dir.FullName);
try
{
ZipFile.ExtractToDirectory(ZipPath, dir.FullName);
}
catch
{
Clear();
}

// and also extract the contained zip in there too with all the xsds in there
if (File.Exists(Path.Combine(dir.FullName, "fhir-all-xsd.zip")))
Expand All @@ -130,9 +137,9 @@ public void Clear()


/// <summary>
/// Gets the cache directory, but does not create one if it does not yet exist
/// Gets the cache directory, or creates an empty cache directory if it does not exist
/// </summary>
/// <returns></returns>
/// <returns>Information about the existing (or new) cache directory</returns>
private DirectoryInfo getCachedZipDirectory()
{
// First, create the main "cache" directory.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ namespace Hl7.Fhir.Specification.Source
/// <summary>Reads FHIR artifacts (Profiles, ValueSets, ...) from a ZIP archive. Thread-safe.</summary>
/// <remarks>Extracts the ZIP archive to a temporary folder and delegates to the <see cref="CommonDirectorySource"/>.</remarks>
[DebuggerDisplay(@"\{{DebuggerDisplay,nq}}")]
public class CommonZipSource : ISummarySource, ICommonConformanceSource, IArtifactSource, IResourceResolver, IAsyncResourceResolver
public class CommonZipSource : ISummarySource, ICommonConformanceSource, IArtifactSource, IAsyncResourceResolver
{
#pragma warning disable IDE1006 // Naming Styles - cannot fix this name because of bw-compatibility
public const string SpecificationZipFileName = "specification.zip";
Expand Down
17 changes: 16 additions & 1 deletion src/Hl7.Fhir.Specification.Shared.Tests/Source/ZipSourceTests.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
using FluentAssertions;
using FluentAssertions.Extensions;
using Hl7.Fhir.Model;
using Hl7.Fhir.Specification.Source;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.IO;
using System.IO.Compression;
using System.Linq;
using Task = System.Threading.Tasks.Task;

namespace Hl7.Fhir.Specification.Tests.Source
{
Expand All @@ -30,7 +34,7 @@ public void ListSummariesExcludingSubdirectories()
{
var zip = unpackTestData(new DirectorySourceSettings { IncludeSubDirectories = false });
var summaries = zip.ListSummaries();
summaries.First().Origin.StartsWith(zip.ExtractPath);
summaries.First().Origin.StartsWith(zip.ExtractPath).Should().BeTrue();

Assert.IsNotNull(summaries, "Collection of summaries should not be null");
Assert.AreEqual(1, summaries.Count(), "In the zipfile there is 1 resource in the root folder.");
Expand All @@ -52,5 +56,16 @@ public void UnpacksToSpecificDirectory()
var summaries = zip.ListSummaries();
summaries.First().Origin.Should().StartWith(extractDir);
}

[TestMethod]
// If this test fails, the specification might have changed. This filename is hardcoded into the validation of a successful ZIP unpack
// (firely-net-sdk/src/Hl7.Fhir.Base/Specification/Source/ZipCacher.cs:74)
public void TestFilePrescence()
{
var zip = ZipSource.CreateValidationSource();
zip.ListSummaries(); // make sure the zip is unpacked, we don't need the return value
// if extractpath is null, something went seriously wrong
File.Exists(Path.Combine(zip.ExtractPath!, "profiles-types.xml")).Should().BeTrue();
}
}
}
24 changes: 24 additions & 0 deletions src/Hl7.Fhir.Support.Poco.Tests/Rest/FhirClientMockTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using Hl7.Fhir.Introspection;
using Hl7.Fhir.Model;
using Hl7.Fhir.Rest;
using Hl7.Fhir.Serialization;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using Moq.Protected;
Expand Down Expand Up @@ -416,6 +417,29 @@ public async T.Task TestCanMockFhirClient()
mock.Verify(c => c.ReadAsync<TestPatient>(It.IsAny<string>(), null, null, null), Times.Once);
}

[TestMethod]
public void TestFhirClientSettings()
{
var fhirClient1 = new BaseFhirClient(
new Uri("http://example.org"), TESTINSPECTOR, new FhirClientSettings { SerializationEngine = FhirSerializationEngineFactory.Strict(TESTINSPECTOR) }
);

MethodInfo? serializationEngineField = fhirClient1.GetType().GetMethod("getSerializationEngine", BindingFlags.NonPublic | BindingFlags.Instance);
serializationEngineField.Should().NotBeNull();

(serializationEngineField!.Invoke(fhirClient1, []) is PocoSerializationEngine).Should().BeTrue();

var fhirClient2 = new BaseFhirClient(
new Uri("http://example.org"), TESTINSPECTOR)
;

(serializationEngineField!.Invoke(fhirClient2, []) is ElementModelSerializationEngine).Should().BeTrue();

fhirClient2.Settings.SerializationEngine = FhirSerializationEngineFactory.Strict(TESTINSPECTOR);

(serializationEngineField!.Invoke(fhirClient2, []) is PocoSerializationEngine).Should().BeTrue();
}


[TestMethod]
public async T.Task TestCanCancelInteraction()
Expand Down

0 comments on commit 9f4752a

Please sign in to comment.