Skip to content

Commit

Permalink
Add new data type: "Fhir" (#378)
Browse files Browse the repository at this point in the history
* add fhir datatype

* update tests

* update tests

* fix comment

* update tests

* fix comments

* fix comments

Co-authored-by: reviewer <[email protected]>
  • Loading branch information
sowu880 and reviewer authored Apr 18, 2022
1 parent d7291f8 commit 7944d36
Show file tree
Hide file tree
Showing 15 changed files with 121 additions and 13 deletions.
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
{% assign coding = msg.coding | first}
{% assign coding = msg.coding | first -%}
"{{coding.code}}"
2 changes: 1 addition & 1 deletion data/Templates/Stu3ToR4/metadata.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"type": "json"
"type": "fhir"
}
Original file line number Diff line number Diff line change
Expand Up @@ -346,12 +346,12 @@ public void GivenCcdaDocument_WhenConverting_ExpectedFhirResourceShouldBeReturne
[MemberData(nameof(GetDataForStu3ToR4))]
public void GivenStu3FhirData_WhenConverting_ExpectedR4FhirResourceShouldBeReturned(string rootTemplate, string inputFile, string expectedFile)
{
var jsonProcessor = new JsonProcessor();
var fhirProcessor = new FhirProcessor();
var templateDirectory = Path.Join(AppDomain.CurrentDomain.BaseDirectory, Constants.TemplateDirectory, "Stu3ToR4");

var inputContent = File.ReadAllText(inputFile);
var expectedContent = File.ReadAllText(expectedFile);
var actualContent = jsonProcessor.Convert(inputContent, rootTemplate, new TemplateProvider(templateDirectory, DataType.Json));
var actualContent = fhirProcessor.Convert(inputContent, rootTemplate, new TemplateProvider(templateDirectory, DataType.Fhir));

var expectedObject = JObject.Parse(expectedContent);
var actualObject = JObject.Parse(actualContent);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,19 +99,14 @@ private static IFhirConverter CreateDataProcessor(DataType dataType)
DataType.Hl7v2 => new Hl7v2Processor(),
DataType.Ccda => new CcdaProcessor(),
DataType.Json => new JsonProcessor(),
DataType.Fhir => new FhirProcessor(),
_ => throw new NotImplementedException($"The conversion from data type {dataType} to FHIR is not supported")
};
}

private static ITemplateProvider CreateTemplateProvider(DataType dataType, string templateDirectory)
{
return dataType switch
{
DataType.Hl7v2 => new TemplateProvider(templateDirectory, DataType.Hl7v2),
DataType.Ccda => new TemplateProvider(templateDirectory, DataType.Ccda),
DataType.Json => new TemplateProvider(templateDirectory, DataType.Json),
_ => throw new NotImplementedException($"The conversion from data type {dataType} to FHIR is not supported")
};
return new TemplateProvider(templateDirectory, dataType);
}

private static TraceInfo CreateTraceInfo(DataType dataType, bool isTraceInfo)
Expand All @@ -127,6 +122,7 @@ private static List<string> GetInputFiles(DataType dataType, string inputDataFol
DataType.Ccda => Directory.EnumerateFiles(inputDataFolder, "*.*", SearchOption.AllDirectories)
.Where(x => CcdaExtensions.Contains(Path.GetExtension(x).ToLower())).ToList(),
DataType.Json => Directory.EnumerateFiles(inputDataFolder, "*.json", SearchOption.AllDirectories).ToList(),
DataType.Fhir => Directory.EnumerateFiles(inputDataFolder, "*.json", SearchOption.AllDirectories).ToList(),
_ => new List<string>(),
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,22 @@ public class ProcessorTests
private static readonly string _hl7v2TestData;
private static readonly string _ccdaTestData;
private static readonly string _jsonTestData;
private static readonly string _fhirStu3TestData;

static ProcessorTests()
{
_hl7v2TestData = File.ReadAllText(Path.Join(TestConstants.SampleDataDirectory, "Hl7v2", "LRI_2.0-NG_CBC_Typ_Message.hl7"));
_ccdaTestData = File.ReadAllText(Path.Join(TestConstants.SampleDataDirectory, "Ccda", "CCD.ccda"));
_jsonTestData = File.ReadAllText(Path.Join(TestConstants.SampleDataDirectory, "Json", "ExamplePatient.json"));
_fhirStu3TestData = File.ReadAllText(Path.Join(TestConstants.SampleDataDirectory, "Stu3", "Patient.json"));
}

public static IEnumerable<object[]> GetValidInputsWithTemplateDirectory()
{
yield return new object[] { new Hl7v2Processor(), new TemplateProvider(TestConstants.Hl7v2TemplateDirectory, DataType.Hl7v2), _hl7v2TestData, "ORU_R01" };
yield return new object[] { new CcdaProcessor(), new TemplateProvider(TestConstants.CcdaTemplateDirectory, DataType.Ccda), _ccdaTestData, "CCD" };
yield return new object[] { new JsonProcessor(), new TemplateProvider(TestConstants.JsonTemplateDirectory, DataType.Json), _jsonTestData, "ExamplePatient" };
yield return new object[] { new FhirProcessor(), new TemplateProvider(TestConstants.FhirStu3TemplateDirectory, DataType.Fhir), _fhirStu3TestData, "Patient" };
}

public static IEnumerable<object[]> GetValidInputsWithTemplateCollection()
Expand All @@ -48,6 +51,7 @@ public static IEnumerable<object[]> GetValidInputsWithTemplateCollection()
yield return new object[] { new Hl7v2Processor(), new TemplateProvider(templateCollection), _hl7v2TestData };
yield return new object[] { new CcdaProcessor(), new TemplateProvider(templateCollection), _ccdaTestData };
yield return new object[] { new JsonProcessor(), new TemplateProvider(templateCollection), _jsonTestData };
yield return new object[] { new FhirProcessor(), new TemplateProvider(templateCollection), _fhirStu3TestData };
}

public static IEnumerable<object[]> GetValidInputsWithProcessSettings()
Expand Down Expand Up @@ -77,6 +81,11 @@ public static IEnumerable<object[]> GetValidInputsWithProcessSettings()
new JsonProcessor(null), new JsonProcessor(new ProcessorSettings()), new JsonProcessor(positiveTimeOutSettings), new JsonProcessor(negativeTimeOutSettings),
new TemplateProvider(TestConstants.TestTemplateDirectory, DataType.Json), _jsonTestData,
};
yield return new object[]
{
new FhirProcessor(null), new FhirProcessor(new ProcessorSettings()), new FhirProcessor(positiveTimeOutSettings), new FhirProcessor(negativeTimeOutSettings),
new TemplateProvider(TestConstants.TestTemplateDirectory, DataType.Fhir), _fhirStu3TestData,
};
}

public static IEnumerable<object[]> GetValidInputsWithLargeForLoop()
Expand All @@ -99,6 +108,12 @@ public static IEnumerable<object[]> GetValidInputsWithLargeForLoop()
new TemplateProvider(TestConstants.TestTemplateDirectory, DataType.Json),
_jsonTestData,
};
yield return new object[]
{
new FhirProcessor(),
new TemplateProvider(TestConstants.TestTemplateDirectory, DataType.Fhir),
_fhirStu3TestData,
};
}

public static IEnumerable<object[]> GetValidInputsWithNestingTooDeep()
Expand All @@ -121,6 +136,12 @@ public static IEnumerable<object[]> GetValidInputsWithNestingTooDeep()
new TemplateProvider(TestConstants.TestTemplateDirectory, DataType.Json),
_jsonTestData,
};
yield return new object[]
{
new FhirProcessor(),
new TemplateProvider(TestConstants.TestTemplateDirectory, DataType.Fhir),
_fhirStu3TestData,
};
}

[Theory]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ public static class TestConstants
public static readonly string Hl7v2TemplateDirectory = Path.Join(TemplateDirectory, "Hl7v2");
public static readonly string CcdaTemplateDirectory = Path.Join(TemplateDirectory, "Ccda");
public static readonly string JsonTemplateDirectory = Path.Join(TemplateDirectory, "Json");
public static readonly string FhirStu3TemplateDirectory = Path.Join(TemplateDirectory, "Stu3ToR4");
public static readonly string TestTemplateDirectory = "TestData/TestTemplates";
public static readonly string ExpectedDirectory = "TestData/Expected/";
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@ public enum DataType
Hl7v2,
Ccda,
Json,
Fhir,
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// -------------------------------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
// -------------------------------------------------------------------------------------------------

using Microsoft.Health.Fhir.Liquid.Converter.Models;

namespace Microsoft.Health.Fhir.Liquid.Converter.Processors
{
public class FhirProcessor : JsonProcessor
{
public FhirProcessor(ProcessorSettings processorSettings = null)
: base(processorSettings)
{
}

public override string Convert(string data, string rootTemplate, ITemplateProvider templateProvider, TraceInfo traceInfo = null)
{
// TO DO For FHIR Specific Logic
// 1. Add FHIR related checks for pre-processor and post-processor.
// 2. Add log for version conversion.
// 3. Add logic to process "extension" and "contained" fields.

return base.Convert(data, rootTemplate, templateProvider, traceInfo);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public class TemplateCollectionFunctionalTests : IAsyncLifetime
private readonly string _defaultHl7v2TemplateImageReference = "microsofthealth/hl7v2templates:default";
private readonly string _defaultCcdaTemplateImageReference = "microsofthealth/ccdatemplates:default";
private readonly string _defaultJsonTemplateImageReference = "microsofthealth/jsontemplates:default";
private readonly string _defaultStu3ToR4TemplateImageReference = "microsofthealth/stu3tor4templates:default";
private readonly string testOneLayerImageReference;
private readonly string testMultiLayerImageReference;
private readonly string testInvalidImageReference;
Expand Down Expand Up @@ -150,6 +151,28 @@ public static IEnumerable<object[]> GetJsonDataAndTemplateSources()
});
}

public static IEnumerable<object[]> GetFhirStu3DataAndTemplateSources()
{
var data = new List<string>
{
@"CapabilityStatement",
@"CodeSystem",
@"Observation",
@"OperationDefinition",
@"OperationOutcome",
@"Parameters",
@"Patient",
@"StructureDefinition",
@"ValueSet",
};
return data.Select(item => new[]
{
Path.Join(_sampleDataDirectory, "Stu3", $"{item}.json"),
Path.Join(_templateDirectory, "Stu3ToR4"),
item,
});
}

public static IEnumerable<object[]> GetNotExistImageInfo()
{
yield return new object[] { "templatetest", "notexist" };
Expand All @@ -173,6 +196,7 @@ public static IEnumerable<object[]> GetDefaultTemplatesInfo()
yield return new object[] { "microsofthealth/hl7v2templates:default", "Hl7v2" };
yield return new object[] { "microsofthealth/ccdatemplates:default", "Ccda" };
yield return new object[] { "microsofthealth/jsontemplates:default", "Json" };
yield return new object[] { "microsofthealth/stu3tor4templates:default", "Stu3ToR4" };
}

[Fact]
Expand Down Expand Up @@ -399,6 +423,28 @@ public async Task GivenJsonSameInputData_WithDifferentTemplateSource_WhenConvert
Assert.True(JToken.DeepEquals(imageResultObject, folderResultObject));
}

[Theory]
[MemberData(nameof(GetFhirStu3DataAndTemplateSources))]
public async Task GivenFhirStu3SameInputData_WithDifferentTemplateSource_WhenConvert_ResultShouldBeIdentical(string inputFile, string defaultTemplateDirectory, string rootTemplate)
{
var folderTemplateProvider = new TemplateProvider(defaultTemplateDirectory, DataType.Fhir);

var templateProviderFactory = new TemplateCollectionProviderFactory(new MemoryCache(new MemoryCacheOptions()), Options.Create(new TemplateCollectionConfiguration()));
var templateProvider = templateProviderFactory.CreateTemplateCollectionProvider(_defaultStu3ToR4TemplateImageReference, string.Empty);
var imageTemplateProvider = new TemplateProvider(await templateProvider.GetTemplateCollectionAsync(CancellationToken.None));

var fhirProcessor = new FhirProcessor();
var inputContent = File.ReadAllText(inputFile);

var imageResult = fhirProcessor.Convert(inputContent, rootTemplate, imageTemplateProvider);
var folderResult = fhirProcessor.Convert(inputContent, rootTemplate, folderTemplateProvider);

var imageResultObject = JObject.Parse(imageResult);
var folderResultObject = JObject.Parse(folderResult);

Assert.True(JToken.DeepEquals(imageResultObject, folderResultObject));
}

private void TestByTemplate(string inputFile, string entryTemplate, List<Dictionary<string, Template>> templateProvider)
{
var hl7v2Processor = new Hl7v2Processor();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public static IEnumerable<object[]> GetValidDefaultTemplateInfo()
yield return new object[] { DataType.Hl7v2, "microsofthealth/hl7v2templates:default", "Hl7v2DefaultTemplates.tar.gz" };
yield return new object[] { DataType.Ccda, "microsofthealth/ccdatemplates:default", "CcdaDefaultTemplates.tar.gz" };
yield return new object[] { DataType.Json, "microsofthealth/jsontemplates:default", "JsonDefaultTemplates.tar.gz" };
yield return new object[] { DataType.Fhir, "microsofthealth/stu3tor4templates:default", "Stu3ToR4DefaultTemplates.tar.gz" };
}

public static IEnumerable<object[]> GetSupportedImageReference()
Expand All @@ -27,6 +28,7 @@ public static IEnumerable<object[]> GetSupportedImageReference()
yield return new object[] { "microsofthealth/hl7v2templates:default" };
yield return new object[] { "microsofthealth/ccdatemplates:default" };
yield return new object[] { "microsofthealth/jsontemplates:default" };
yield return new object[] { "microsofthealth/stu3tor4templates:default" };
}

public static IEnumerable<object[]> GetSupportedImageReferenceWithCaseInsensitive()
Expand All @@ -37,6 +39,7 @@ public static IEnumerable<object[]> GetSupportedImageReferenceWithCaseInsensitiv
yield return new object[] { "MICROSOFTHEALTH/hl7v2templates:default" };
yield return new object[] { "microsofthealth/ccdatemplates:DEFAULT" };
yield return new object[] { "microsofthealth/JSONtemplates:DEFAULT" };
yield return new object[] { "microsofthealth/STU3ToR4templates:DEFAULT" };
}

public static IEnumerable<object[]> GetUnSupportedImageReference()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ public static IEnumerable<object[]> GetDefaultTemplateReference()
yield return new object[] { "microsofthealth/hl7v2templates:default" };
yield return new object[] { "microsofthealth/ccdatemplates:default" };
yield return new object[] { "microsofthealth/jsontemplates:default" };
yield return new object[] { "microsofthealth/stu3tor4templates:default" };
}

public static IEnumerable<object[]> GetDefaultTemplateReferenceWithCaseInsensitive()
Expand All @@ -95,6 +96,7 @@ public static IEnumerable<object[]> GetDefaultTemplateReferenceWithCaseInsensiti
yield return new object[] { "MicrosoftHealth/Hl7v2Templates:default" };
yield return new object[] { "microsoftHealth/CcdaTemplates:default" };
yield return new object[] { "microsoftHealth/JSONTemplates:default" };
yield return new object[] { "microsoftHealth/STu3tor4Templates:default" };
}

public static IEnumerable<object[]> GetInvalidDefaultTemplateReference()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ public TemplateCollectionProviderTests()
_cache.Set("microsofthealth/ccdatemplates:default", ccdaDefaultTemplateLayer, memoryOption);
TemplateLayer jsonDefaultTemplateLayer = TemplateLayer.ReadFromEmbeddedResource("JsonDefaultTemplates.tar.gz");
_cache.Set("microsofthealth/jsontemplates:default", jsonDefaultTemplateLayer, memoryOption);
TemplateLayer stu3ToR4DefaultTemplateLayer = TemplateLayer.ReadFromEmbeddedResource("Stu3ToR4DefaultTemplates.tar.gz");
_cache.Set("microsofthealth/stu3tor4templates:default", stu3ToR4DefaultTemplateLayer, memoryOption);

PushLargeSizeManifest();
}
Expand Down Expand Up @@ -85,10 +87,11 @@ public static IEnumerable<object[]> GetImageInfoForArtifactWithTag()

public static IEnumerable<object[]> GetDefaultTemplatesInfo()
{
yield return new object[] { "microsofthealth/fhirconverter:default", 852 };
yield return new object[] { "microsofthealth/hl7v2templates:default", 852 };
yield return new object[] { "microsofthealth/fhirconverter:default", 915 };
yield return new object[] { "microsofthealth/hl7v2templates:default", 915 };
yield return new object[] { "microsofthealth/ccdatemplates:default", 821 };
yield return new object[] { "microsofthealth/jsontemplates:default", 2 };
yield return new object[] { "microsofthealth/stu3tor4templates:default", 261 };
}

[Theory]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public class TemplateCollectionProviderFactoryTests
private static readonly string _defaultHl7v2TemplateImageReference = "microsofthealth/hl7v2templates:default";
private static readonly string _defaultCcdaTemplateImageReference = "microsofthealth/ccdatemplates:default";
private static readonly string _defaultJsonTemplateImageReference = "microsofthealth/jsontemplates:default";
private static readonly string _defaultStu3ToR4TemplateImageReference = "microsofthealth/stu3tor4templates:default";

public static IEnumerable<object[]> GetValidImageInfoWithTag()
{
Expand All @@ -45,6 +46,7 @@ public static IEnumerable<object[]> GetDefaultTemplateTarGzFile()
yield return new object[] { "Hl7v2NewDefaultTemplates.tar.gz", _defaultHl7v2TemplateImageReference, Path.Join(_testTemplatesPath, "Hl7v2") };
yield return new object[] { "CcdaNewDefaultTemplates.tar.gz", _defaultCcdaTemplateImageReference, Path.Join(_testTemplatesPath, "Ccda") };
yield return new object[] { "JsonNewDefaultTemplates.tar.gz", _defaultJsonTemplateImageReference, Path.Join(_testTemplatesPath, "Json") };
yield return new object[] { "Stu3ToR4NewDefaultTemplates.tar.gz", _defaultStu3ToR4TemplateImageReference, Path.Join(_testTemplatesPath, "Stu3ToR4") };
}

public static IEnumerable<object[]> GetDefaultImageReference()
Expand All @@ -53,6 +55,7 @@ public static IEnumerable<object[]> GetDefaultImageReference()
yield return new object[] { _defaultHl7v2TemplateImageReference };
yield return new object[] { _defaultCcdaTemplateImageReference };
yield return new object[] { _defaultJsonTemplateImageReference };
yield return new object[] { _defaultStu3ToR4TemplateImageReference };
}

[Theory]
Expand Down
Loading

0 comments on commit 7944d36

Please sign in to comment.