Skip to content

Commit

Permalink
Release v1.10.0 - See CHANGELOG.md
Browse files Browse the repository at this point in the history
  • Loading branch information
philipwilford committed Sep 13, 2021
1 parent fe75aa0 commit 0adb57e
Show file tree
Hide file tree
Showing 14 changed files with 631 additions and 10 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
### Change Log/Revision History

NOTE: WHEN UPDATING THIS LIBRARY
If you update the config.xml file, this file needs to be copied to the MedsView mapper project
AND the mhrSimulator (cdaExtractorConfig.xml)

1.10.0
-------------
Added "Australian Immunisation Register" Data
Added "Pharmacist Shared Medicines List" Data

1.9.0
-------------
Added "Pathology Report" Data
Expand Down
4 changes: 2 additions & 2 deletions src/CdaExtractor.Sample/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,5 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.9.0.0")]
[assembly: AssemblyFileVersion("1.9.0.0")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
11 changes: 10 additions & 1 deletion src/CdaExtractor/CdaDataExtractor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ public CdaDocument Extract(XmlDocument cdaDocument)
var immunisationsEx = new ImmunisationsExtractor(documentXPaths);
var immunisations = immunisationsEx.Extract(cdaXmlDocument);

var immunisationRegisterEx = new ImmunisationRegisterExtractor(documentXPaths);
var immunisationRegister = immunisationRegisterEx.Extract(cdaXmlDocument);


var consumerNoteEx = new ConsumerNoteExtractor(documentXPaths);
var consumerNote = consumerNoteEx.Extract(cdaXmlDocument);

Expand All @@ -76,6 +80,9 @@ public CdaDocument Extract(XmlDocument cdaDocument)
var pathologyExtractor = new PathologyExtractor(documentXPaths);
var pathology = pathologyExtractor.Extract(cdaXmlDocument);

var psmlExtractor = new PsmlExtractor(documentXPaths);
var psml = psmlExtractor.Extract(cdaXmlDocument);

var document = new CdaDocument
{
Author = author,
Expand All @@ -85,11 +92,13 @@ public CdaDocument Extract(XmlDocument cdaDocument)
DocumentMetadata = documentMetadata,
SubjectOfCare = subjectOfCare,
ImmunisationItems = immunisations,
ImmunisationRegisterItems = immunisationRegister,
ConsumerNote = consumerNote,
AdvanceCareInformation = advanceCareInformation,
PharmaceuticalBenefitItems = pbs,
Pathology = pathology,
DiagnosticImaging = diagnosticImaging
DiagnosticImaging = diagnosticImaging,
Psml = psml
};

return document;
Expand Down
4 changes: 4 additions & 0 deletions src/CdaExtractor/CdaExtractor.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,13 @@
<Compile Include="Extractor\AdvanceCareInformationExtractor.cs" />
<Compile Include="Extractor\AuthorExtractor.cs" />
<Compile Include="Extractor\ConsumerNoteExtractor.cs" />
<Compile Include="Extractor\ImmunisationRegisterExtractor.cs" />
<Compile Include="Extractor\ImmunisationsExtractor.cs" />
<Compile Include="Extractor\DocumentMetadataExtractor.cs" />
<Compile Include="Extractor\ICdaExtractor.cs" />
<Compile Include="Extractor\MedicalHistoryExtractor.cs" />
<Compile Include="Extractor\DiagnosticImagingExtractor.cs" />
<Compile Include="Extractor\PsmlExtractor.cs" />
<Compile Include="Extractor\PharmaceuticalBenefitItemExtractor.cs" />
<Compile Include="Extractor\PathologyExtractor.cs" />
<Compile Include="Extractor\SubjectOfCareExtractor.cs" />
Expand All @@ -64,6 +66,8 @@
<Compile Include="IDocumentXPathProvider.cs" />
<Compile Include="Model\DiagnosticImaging.cs" />
<Compile Include="Model\ImagingExaminationResult.cs" />
<Compile Include="Model\ImmunisationRegister.cs" />
<Compile Include="Model\Psml.cs" />
<Compile Include="Model\PathologyTestResult.cs" />
<Compile Include="Model\Pathology.cs" />
<Compile Include="Model\AdverseReaction.cs" />
Expand Down
9 changes: 9 additions & 0 deletions src/CdaExtractor/CdaXmlDocument.cs
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,11 @@ public Id GetId(XmlNode node, string xpath)

#region DateTime / Interval Functions

public DateTime? GetDateTime(string value)
{
return string.IsNullOrWhiteSpace(value) ? null : DateTimeHelper.ConvertISO8601DateTimeStringToDateTime(value);
}

public DateTime? GetDateTimeValue(string xpath)
{
return string.IsNullOrWhiteSpace(xpath) ? null : DateTimeHelper.ConvertISO8601DateTimeStringToDateTime(GetString(xpath));
Expand Down Expand Up @@ -377,6 +382,10 @@ private static XmlNode GetPreferredName(XmlNodeList nameNodes)
}

#endregion




}

public static class Extensions
Expand Down
152 changes: 148 additions & 4 deletions src/CdaExtractor/Extractor/DocumentMetadataExtractor.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Xml;
using Nehta.VendorLibrary.CdaExtractor.Model;

namespace Nehta.VendorLibrary.CdaExtractor.Extractor
Expand All @@ -7,6 +10,10 @@ public class DocumentMetadataExtractor : ICdaExtractor<DocumentMetadata>
{
private readonly IDictionary<string, string> _documentXPaths;

private DateTime _effectiveDateTime;
private DateTime _eventStartDateTime;
private DateTime _eventEndDateTime;

public DocumentMetadataExtractor(IDictionary<string, string> documentXPaths)
{
_documentXPaths = documentXPaths;
Expand All @@ -17,8 +24,12 @@ public DocumentMetadata Extract(CdaXmlDocument cdaDocument)
// Document code
var documentCode = cdaDocument.GetCodableText(_documentXPaths.Get("DocumentCode"));

// Effective time
var effectiveDateTime = cdaDocument.GetDateTimeValue(_documentXPaths.Get("EffectiveTime"));
// Effective time - if this fails, there is a problem!
var effectiveTime = cdaDocument.GetDateTimeValue(_documentXPaths.Get("EffectiveTime"));
_effectiveDateTime = effectiveTime.HasValue ? effectiveTime.Value : DateTime.Now;

// For Certain Documents get a different DateTime
SetDateTimes(cdaDocument, documentCode.Code);

// Document ID
var documentId = cdaDocument.GetId(_documentXPaths.Get("DocumentId"));
Expand All @@ -37,13 +48,146 @@ public DocumentMetadata Extract(CdaXmlDocument cdaDocument)
{
TemplateId = cdaDocument.TemplateId,
DocumentCode = documentCode,
EffectiveTime = effectiveDateTime,
EffectiveTime = _effectiveDateTime,
EventStartDateTime = _eventStartDateTime,
EventEndDateTime = _eventEndDateTime,
DocumentId = documentId,
Title = title,
LinkId = linkId
};

return documentMetadata;
}

void SetDateTimes(CdaXmlDocument cdaDocument, string documentTypeCode)
{
// Set service start and stop time
if (documentTypeCode == "51852-2")
{
// If document is Specialist Letter
_eventStartDateTime = _effectiveDateTime;
_eventEndDateTime = _effectiveDateTime;
}
else if (documentTypeCode == "100.16764")
{
// If document is Prescription Record
var authorTime = cdaDocument.GetDateTimeValue("/cda:ClinicalDocument/cda:author/cda:time/@value");

_eventStartDateTime = authorTime.HasValue? authorTime.Value : _effectiveDateTime;
_eventEndDateTime = _eventStartDateTime;
}
else if (documentTypeCode == "100.16765")
{
// If document is PCEHR Dispense Record
var supplyTime = cdaDocument.GetDateTimeValue("/cda:ClinicalDocument/cda:component/cda:structuredBody/" +
"cda:component/cda:section[cda:code/@code='102.16210' and cda:code/@codeSystem='1.2.36.1.2001.1001.101']/cda:entry/" +
"cda:substanceAdministration/cda:entryRelationship/cda:supply/cda:_effectiveDateTime/@value");

_eventStartDateTime = supplyTime.HasValue ? supplyTime.Value : _effectiveDateTime;
_eventEndDateTime = _eventStartDateTime;
}
else if (documentTypeCode == "100.32001")
{
// R5: If document is Pathology Report - Could contain multiple records
// Need to get LATEST Date - if multiple returned

XmlNodeList nList = cdaDocument.SelectNodes("/cda:ClinicalDocument/cda:component/cda:structuredBody/cda:component" +
"/cda:section[cda:code/@code='101.20018']/cda:component" +
"/cda:section[cda:code/@code='102.16144']/cda:entry/cda:observation" +
"/cda:entryRelationship/cda:observation[cda:code/@code='102.16156']" +
"/cda:effectiveTime/@value");

var firstCollectionDateTime = "";
var lastCollectionDateTime = "";
if (nList.Count == 1)
{
firstCollectionDateTime = nList[0].Value;
lastCollectionDateTime = nList[0].Value;
}
else if (nList.Count > 1)
{
string[] sDates = new string[nList.Count];
for (int i = 0; i < nList.Count; i++)
{
sDates[i] = nList[i].Value;
}
Array.Sort(sDates);
//Get last entry
firstCollectionDateTime = sDates[0];
lastCollectionDateTime = sDates[nList.Count - 1];
}

_eventStartDateTime = !string.IsNullOrWhiteSpace(firstCollectionDateTime)
? cdaDocument.GetDateTime(firstCollectionDateTime).Value
: _effectiveDateTime;
_eventEndDateTime = !string.IsNullOrWhiteSpace(lastCollectionDateTime)
? cdaDocument.GetDateTime(lastCollectionDateTime).Value
: _effectiveDateTime;
}
else if (documentTypeCode == "100.16957")
{
// R5: If document is Diagnostic Imaging - Could contain multiple records
// Need to get LATEST Date - if multiple returned

XmlNodeList nList = cdaDocument.SelectNodes("/cda:ClinicalDocument/cda:component/cda:structuredBody/cda:component" +
"/cda:section/cda:component/cda:section/cda:entry/cda:observation" +
"/cda:entryRelationship/cda:act[cda:code/@code='102.16511']/cda:entryRelationship" +
"/cda:observation/cda:effectiveTime/@value");
var firstImagingDateTime = "";
var lastImagingDateTime = "";
if (nList.Count == 1)
{
firstImagingDateTime = nList[0].Value;
lastImagingDateTime = nList[0].Value;
}
else if (nList.Count > 1)
{
string[] sDates = new string[nList.Count];
for (int i = 0; i < nList.Count; i++)
{
sDates[i] = nList[i].Value;
}
Array.Sort(sDates);
//Get last entry
firstImagingDateTime = sDates[0];
lastImagingDateTime = sDates[nList.Count - 1];
}

_eventStartDateTime = !string.IsNullOrWhiteSpace(firstImagingDateTime)
? cdaDocument.GetDateTime(firstImagingDateTime).Value
: _effectiveDateTime;
_eventEndDateTime = !string.IsNullOrWhiteSpace(lastImagingDateTime)
? cdaDocument.GetDateTime(lastImagingDateTime).Value
: _effectiveDateTime;
}
else if (documentTypeCode == "100.16975")
{
// Advance Care Planning Document
var authorTime = cdaDocument.GetDateTimeValue("/cda:ClinicalDocument/cda:component/cda:structuredBody/cda:component/cda:section[cda:code/@code='101.16973']/cda:entry/cda:act/cda:author/cda:time/@value");
_eventStartDateTime = authorTime.Value;
_eventEndDateTime = _eventStartDateTime;
}
else
{
// For other document types set service start and stop time to encompassingEncounter/_effectiveDateTime if available
var startTime1 = cdaDocument.GetDateTimeValue("/cda:ClinicalDocument/cda:componentOf/cda:encompassingEncounter/cda:_effectiveDateTime/@value");
var startTime2 = cdaDocument.GetDateTimeValue("/cda:ClinicalDocument/cda:componentOf/cda:encompassingEncounter/cda:_effectiveDateTime/cda:low/@value");
var stopTime = cdaDocument.GetDateTimeValue("/cda:ClinicalDocument/cda:componentOf/cda:encompassingEncounter/cda:_effectiveDateTime/cda:high/@value");

_eventStartDateTime = startTime1.HasValue
? startTime1.Value
: startTime2.HasValue
? startTime2.Value
: _effectiveDateTime;

_eventEndDateTime = stopTime.HasValue
? stopTime.Value
: startTime1.HasValue
? startTime1.Value
: _effectiveDateTime;

}
}

}
}
33 changes: 33 additions & 0 deletions src/CdaExtractor/Extractor/ImmunisationRegisterExtractor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using System.Collections.Generic;
using System.Linq;
using System.Xml;
using Nehta.VendorLibrary.CdaExtractor.Model;

namespace Nehta.VendorLibrary.CdaExtractor.Extractor
{
public class ImmunisationRegisterExtractor : ICdaExtractor<List<ImmunisationRegister>>
{
private readonly IDictionary<string, string> _documentXPaths;

public ImmunisationRegisterExtractor(IDictionary<string, string> documentXPaths)
{
_documentXPaths = documentXPaths;
}

public List<ImmunisationRegister> Extract(CdaXmlDocument document)
{
var nodes = document.SelectNodes(_documentXPaths.Get("ImmunisationRegister"));
if(nodes == null || nodes.Count == 0) return null;

return
(from XmlNode node in nodes
select new ImmunisationRegister
{
DateTime = document.GetDateTimeValue(node, _documentXPaths.Get("ImmunisationDateTime")),
Immunisation = document.GetRelativeCode(node, _documentXPaths.Get("Immunisation")),
BrandName = document.GetRelativeCode(node, _documentXPaths.Get("BrandName"))
}
).ToList();
}
}
}
38 changes: 38 additions & 0 deletions src/CdaExtractor/Extractor/PsmlExtractor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using System.Collections.Generic;
using System.Linq;
using System.Xml;
using Nehta.VendorLibrary.CdaExtractor.Model;

namespace Nehta.VendorLibrary.CdaExtractor.Extractor
{
public class PsmlExtractor : ICdaExtractor<Psml>
{
private readonly IDictionary<string, string> _documentXPaths;

public PsmlExtractor(IDictionary<string, string> documentXPaths)
{
_documentXPaths = documentXPaths;
}

public Psml Extract(CdaXmlDocument cdaDocument)
{
var psml = new Psml();

var attachmentNode = cdaDocument.SelectSingleNode(_documentXPaths.Get("Attachment"));

if (attachmentNode != null)
{
var attachmentIntegrityCheck = cdaDocument.SelectSingleNode(attachmentNode, _documentXPaths.Get("AttachmentIntegrityCheck"));
if (attachmentIntegrityCheck != null) psml.ReportIntegrityCheck = attachmentIntegrityCheck.Value;

var attachmentMediaType = cdaDocument.SelectSingleNode(attachmentNode, _documentXPaths.Get("AttachmentMediaType"));
if (attachmentMediaType != null) psml.ReportMediaType = attachmentMediaType.Value;

var attachmentName = cdaDocument.SelectSingleNode(attachmentNode, _documentXPaths.Get("AttachmentName"));
if (attachmentName != null) psml.ReportDocName = attachmentName.Value;
}

return psml;
}
}
}
4 changes: 4 additions & 0 deletions src/CdaExtractor/Model/CdaDocument.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,13 @@ public class CdaDocument
public List<PharmaceuticalBenefitItem> PharmaceuticalBenefitItems { get; set; }
public List<MedicalHistory> MedicalHistoryItems { get; set; }
public List<Immunisation> ImmunisationItems { get; set; }
public List<ImmunisationRegister> ImmunisationRegisterItems { get; set; }
public ConsumerNote ConsumerNote { get; set; }
public AdvanceCareInformation AdvanceCareInformation { get; set; }
public Pathology Pathology { get; set; }
public DiagnosticImaging DiagnosticImaging { get; set; }
public Psml Psml { get; set; }


}
}
2 changes: 2 additions & 0 deletions src/CdaExtractor/Model/DocumentMetadata.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,7 @@ public class DocumentMetadata
public string Title { get; set; }
public DateTime? EffectiveTime { get; set; }
public Id LinkId { get; set; }
public DateTime? EventStartDateTime { get; set; }
public DateTime? EventEndDateTime { get; set; }
}
}
11 changes: 11 additions & 0 deletions src/CdaExtractor/Model/ImmunisationRegister.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using System;

namespace Nehta.VendorLibrary.CdaExtractor.Model
{
public class ImmunisationRegister
{
public DateTime? DateTime { get; set; }
public CodableText Immunisation { get; set; }
public CodableText BrandName { get; set; }
}
}
Loading

0 comments on commit 0adb57e

Please sign in to comment.