Unable to Parse CSV from Business Service to Business Process
Dear All,
I’m having trouble creating the following business service. It’s intention is to pick up an CSV via FTP and pass it to a Business process that transforms it to a HL7 message.
I have created a record map for the CSV file, which I am trying to call in the business service and parse it into a new message class, which can be transformed in the business process.
Please could you advise:
Business Service:
/// Collects CSV from Epic FTP, looking for ENH patient
/// antiobitic sensitivities to be passed on to ENH Infection control
/// Patch 176
Class CUH.Serv.EpicFTPFilePickup Extends (Ens.BusinessService, CUH.Recordmap.ENHSens2HL7)
{
Parameter ADAPTER = "EnsLib.FTP.InboundAdapter";
// Adds Option to state which Business process is the target of the Business service
Parameter SETTINGS As %String = "TargetConfigName";
// Declares that the TargetConfigName as a %String
Property TargetConfigName As %String(MAXLEN = 999);
// previous pInput: pInput As %RegisteredObject & Output pOutput As %RegisteredObject
Method OnProcessInput(pInput As %IO.DeviceStream, Output pOutput As %RegisteredObject) As %Status
{
//Create Request Message
//set trequest = ##class(CUH.Recordmap.ENHSens2HL7)
do ##class(CUH.Recordmap.PutObject).%New()
//Send Request to CUH.Proc.ICENETROUTER
set tgo = ..SendRequestAsync(..TargetConfigName,trequest)
Quit $$$ERROR($$$NotImplemented)
}
}Record map (using CSV mapping tool).
Class CUH.Recordmap.ENHSens2HL7 Extends EnsLib.RecordMap.RecordMap
{
Parameter OBJECTNAME = "CUH.Recordmap.ENHSens2HL7.Record";
/// Method to write a record to a stream or device. This method will be generated based on the
/// structure of the RecordMap. For testing purposes, a file name may be passed in the pStream argument.
ClassMethod PutObject(pStream As %IO.DeviceStream, pObject As %RegisteredObject, pFlush As %Boolean = 1, ByRef pPadArray As %String) As %Status
{
Try {
Set tStatus = $$$OK
If '$IsObject(pStream) {
Set tFilename = pStream
Set pStream = ##class(%IO.FileStream).%New()
Do pStream.Open(tFilename,"WAE",,"UTF-8", .tStatus)
If $$$ISERR(tStatus) Quit
}
Set tHasTopFields = $parameter(pObject,"INCLUDETOPFIELDS")
Set pStream.CharEncoding = "UTF-8"
Set tStatus = ..PutRecord(pStream, pObject, tHasTopFields, .pPadArray)
If $$$ISERR(tStatus) Quit
If pFlush Do pStream.Flush(.tStatus)
If $$$ISERR(tStatus) Quit
}
Catch ex {
Set tStatus = ex.AsStatus()
}
Quit tStatus
}
/// Method to retrieve a record from a stream or device. This method will be generated based on the
/// structure of the RecordMap. For testing purposes, a file name may be passed in the pStream argument.
ClassMethod GetObject(pStream As %IO.DeviceStream, Output pObject As %RegisteredObject, pTimeout As %Numeric = -1, ByRef pLookAhead As %String = "", pLabelFound As %Boolean = 0) As %Status
{
Try {
Set tStatus = $$$OK
Set pObject = $$$NULLOREF
If '$IsObject(pStream) {
Set tFilename = pStream
Set pStream = ##class(%IO.FileStream).%New()
Do pStream.Open(tFilename,,pTimeout,"UTF-8", .tStatus)
If $$$ISERR(tStatus) Quit
}
Set tObjectName = $parameter($this,"OBJECTNAME")
Set tObject = $classmethod(tObjectName,"%New")
If '$IsObject(tObject) {
Set tStatus = $$$ERROR($$$CannotCreateObject,tObjectName)
Quit
}
Set tObject.%Source = pStream.Name
Set tGetTopFields = $parameter(tObject,"INCLUDETOPFIELDS")
If pStream.AtEnd {
Set tStatus = $$$ERROR($$$EnsRecordMapErrStreamAtEnd, pStream.Name)
Quit
}
Set pStream.CharEncoding = "UTF-8"
do pStream.WriteLine(1)
#; Parse incoming stream
Set tStatus = ..GetRecord(pStream, tObject, tGetTopFields, pTimeout, pLookAhead, pLabelFound)
If $$$ISERR(tStatus) Quit
}
Catch ex {
Set tStatus = ex.AsStatus()
}
If $$$ISERR(tStatus) { Set pObject = $$$NULLOREF }
Else { Set pObject = tObject }
Quit tStatus
}
/// Internal helper method to output object to a stream
ClassMethod PutRecord(pStream As %IO.DeviceStream, pObject As %RegisteredObject, pHasTopFields As %Boolean, ByRef pPadArray As %String) As %Status [ Internal, Private ]
{
Set tStatus = $$$OK
Do pStream.Write($select(pHasTopFields: ..Escape(##class(CUH.Recordmap.ENHSens2HL7.Record).SpecimenIDLogicalToDisplay(pObject.SpecimenID), $lb($char(44)),"quote",$char(34)), 1: ""),0)
Do pStream.Write($char(44) _ $select(pHasTopFields: ..Escape(##class(CUH.Recordmap.ENHSens2HL7.Record).PatientSurnameLogicalToDisplay(pObject.PatientSurname), $lb($char(44)),"quote",$char(34)), 1: ""),0)
Do pStream.Write($char(44) _ $select(pHasTopFields: ..Escape(##class(CUH.Recordmap.ENHSens2HL7.Record).PatientFirstNameLogicalToDisplay(pObject.PatientFirstName), $lb($char(44)),"quote",$char(34)), 1: ""),0)
Do pStream.Write($char(44) _ $select(pHasTopFields: ..Escape(##class(CUH.Recordmap.ENHSens2HL7.Record).DOBLogicalToDisplay(pObject.DOB), $lb($char(44)),"quote",$char(34)), 1: ""),0)
Do pStream.Write($char(44) _ $select(pHasTopFields: ..Escape(##class(CUH.Recordmap.ENHSens2HL7.Record).PatientNHSNumberLogicalToDisplay(pObject.PatientNHSNumber), $lb($char(44)),"quote",$char(34)), 1: ""),0)
Do pStream.Write($char(44) _ $select(pHasTopFields: ..Escape(##class(CUH.Recordmap.ENHSens2HL7.Record).MRNLogicalToDisplay(pObject.MRN), $lb($char(44)),"quote",$char(34)), 1: ""),0)
Do pStream.Write($char(44) _ $select(pHasTopFields: ..Escape(##class(CUH.Recordmap.ENHSens2HL7.Record).CollectedLogicalToDisplay(pObject.Collected), $lb($char(44)),"quote",$char(34)), 1: ""),0)
Do pStream.Write($char(44) _ $select(pHasTopFields: ..Escape(##class(CUH.Recordmap.ENHSens2HL7.Record).ReceivedLogicalToDisplay(pObject.Received), $lb($char(44)),"quote",$char(34)), 1: ""),0)
Do pStream.Write($char(44) _ $select(pHasTopFields: ..Escape(##class(CUH.Recordmap.ENHSens2HL7.Record).ResultedLogicalToDisplay(pObject.Resulted), $lb($char(44)),"quote",$char(34)), 1: ""),0)
Do pStream.Write($char(44) _ $select(pHasTopFields: ..Escape(##class(CUH.Recordmap.ENHSens2HL7.Record).VerifiedLogicalToDisplay(pObject.Verified), $lb($char(44)),"quote",$char(34)), 1: ""),0)
Do pStream.Write($char(44) _ $select(pHasTopFields: ..Escape(##class(CUH.Recordmap.ENHSens2HL7.Record).SpecimenTypeLogicalToDisplay(pObject.SpecimenType), $lb($char(44)),"quote",$char(34)), 1: ""),0)
Do pStream.Write($char(44) _ $select(pHasTopFields: ..Escape(##class(CUH.Recordmap.ENHSens2HL7.Record).SourceLogicalToDisplay(pObject.Source), $lb($char(44)),"quote",$char(34)), 1: ""),0)
Do pStream.Write($char(44) _ $select(pHasTopFields: ..Escape(##class(CUH.Recordmap.ENHSens2HL7.Record).TestLogicalToDisplay(pObject.Test), $lb($char(44)),"quote",$char(34)), 1: ""),0)
Do pStream.Write($char(44) _ $select(pHasTopFields: ..Escape(##class(CUH.Recordmap.ENHSens2HL7.Record).OrganismLogicalToDisplay(pObject.Organism), $lb($char(44)),"quote",$char(34)), 1: ""),0)
Do pStream.Write($char(44) _ $select(pHasTopFields: ..Escape(##class(CUH.Recordmap.ENHSens2HL7.Record).AntibioticLogicalToDisplay(pObject.Antibiotic), $lb($char(44)),"quote",$char(34)), 1: ""),0)
Do pStream.Write($char(44) _ $select(pHasTopFields: ..Escape(##class(CUH.Recordmap.ENHSens2HL7.Record).AntibioticInterpretationLogicalToDisplay(pObject.AntibioticInterpretation), $lb($char(44)),"quote",$char(34)), 1: ""),0)
Do pStream.Write($char(44) _ $select(pHasTopFields: ..Escape(##class(CUH.Recordmap.ENHSens2HL7.Record).SubmitterLogicalToDisplay(pObject.Submitter), $lb($char(44)),"quote",$char(34)), 1: ""),0)
Do pStream.Write($char(44) _ $select(pHasTopFields: ..Escape(##class(CUH.Recordmap.ENHSens2HL7.Record).ReqExtPatientIDLogicalToDisplay(pObject.ReqExtPatientID), $lb($char(44)),"quote",$char(34)), 1: ""),0)
Do pStream.Write($char(13,10), 0, .tStatus)
If $$$ISERR(tStatus) Quit tStatus
Quit tStatus
}
/// Internal helper method to perform parse of incoming data
ClassMethod GetRecord(pStream As %IO.DeviceStream, pObject As %RegisteredObject, pGetTopFields As %Boolean, pTimeout As %Numeric, ByRef pLookAhead As %String = "", pLabelFound As %Boolean = 0) As %Status [ Internal, Private ]
{
Set tStatus = $$$OK
If pLabelFound { Set tRecLabel = "" }
Else { Set tRecLabel = "" }
Set tStatus = ..chunkRecord(pStream, .tRecordData, .tCharCount, "", pTimeout, $char(13,10), tRecLabel, pLookAhead, $char(34))
If $$$ISERR(tStatus) Quit tStatus
Set tMaxLocal = $$$MaxLocalLength
Set tRecordData("charcount") = +$get(tCharCount)
Set tCurrChunk = 1
Set tTopPiece = 1
Set tCurrSep = 1
Set tStrings = 1
Set tSeps = $listbuild($char(44))
If '$data(tRecordData(tCurrChunk, "block")) {
Set tCurrString = $piece(tRecordData(tCurrChunk), $char(44), tTopPiece)
}
Else {
Set tCurrString = tRecordData(tCurrChunk)
Set tCurrPiece = 1
}
Do ..checkMerge(.tCurrChunk, .tRecordData, .tCurrString, $char(44), .tTopPiece)
If pGetTopFields {
Set pObject.SpecimenID = tCurrString
}
If '$data(tRecordData(tCurrChunk, "block")) {
Set tCurrString = $piece(tRecordData(tCurrChunk), $char(44), tTopPiece)
}
Do ..checkMerge(.tCurrChunk, .tRecordData, .tCurrString, $char(44), .tTopPiece)
If pGetTopFields {
Set pObject.PatientSurname = tCurrString
}
If '$data(tRecordData(tCurrChunk, "block")) {
Set tCurrString = $piece(tRecordData(tCurrChunk), $char(44), tTopPiece)
}
Do ..checkMerge(.tCurrChunk, .tRecordData, .tCurrString, $char(44), .tTopPiece)
If pGetTopFields {
Set pObject.PatientFirstName = tCurrString
}
If '$data(tRecordData(tCurrChunk, "block")) {
Set tCurrString = $piece(tRecordData(tCurrChunk), $char(44), tTopPiece)
}
Do ..checkMerge(.tCurrChunk, .tRecordData, .tCurrString, $char(44), .tTopPiece)
If pGetTopFields {
Set pObject.DOB = tCurrString
}
If '$data(tRecordData(tCurrChunk, "block")) {
Set tCurrString = $piece(tRecordData(tCurrChunk), $char(44), tTopPiece)
}
Do ..checkMerge(.tCurrChunk, .tRecordData, .tCurrString, $char(44), .tTopPiece)
If pGetTopFields {
Set pObject.PatientNHSNumber = tCurrString
}
If '$data(tRecordData(tCurrChunk, "block")) {
Set tCurrString = $piece(tRecordData(tCurrChunk), $char(44), tTopPiece)
}
Do ..checkMerge(.tCurrChunk, .tRecordData, .tCurrString, $char(44), .tTopPiece)
If pGetTopFields {
Set pObject.MRN = tCurrString
}
If '$data(tRecordData(tCurrChunk, "block")) {
Set tCurrString = $piece(tRecordData(tCurrChunk), $char(44), tTopPiece)
}
Do ..checkMerge(.tCurrChunk, .tRecordData, .tCurrString, $char(44), .tTopPiece)
If pGetTopFields {
Set pObject.Collected = tCurrString
}
If '$data(tRecordData(tCurrChunk, "block")) {
Set tCurrString = $piece(tRecordData(tCurrChunk), $char(44), tTopPiece)
}
Do ..checkMerge(.tCurrChunk, .tRecordData, .tCurrString, $char(44), .tTopPiece)
If pGetTopFields {
Set pObject.Received = tCurrString
}
If '$data(tRecordData(tCurrChunk, "block")) {
Set tCurrString = $piece(tRecordData(tCurrChunk), $char(44), tTopPiece)
}
Do ..checkMerge(.tCurrChunk, .tRecordData, .tCurrString, $char(44), .tTopPiece)
If pGetTopFields {
Set pObject.Resulted = tCurrString
}
If '$data(tRecordData(tCurrChunk, "block")) {
Set tCurrString = $piece(tRecordData(tCurrChunk), $char(44), tTopPiece)
}
Do ..checkMerge(.tCurrChunk, .tRecordData, .tCurrString, $char(44), .tTopPiece)
If pGetTopFields {
Set pObject.Verified = tCurrString
}
If '$data(tRecordData(tCurrChunk, "block")) {
Set tCurrString = $piece(tRecordData(tCurrChunk), $char(44), tTopPiece)
}
Do ..checkMerge(.tCurrChunk, .tRecordData, .tCurrString, $char(44), .tTopPiece)
If pGetTopFields {
Set pObject.SpecimenType = tCurrString
}
If '$data(tRecordData(tCurrChunk, "block")) {
Set tCurrString = $piece(tRecordData(tCurrChunk), $char(44), tTopPiece)
}
Do ..checkMerge(.tCurrChunk, .tRecordData, .tCurrString, $char(44), .tTopPiece)
If pGetTopFields {
Set pObject.Source = tCurrString
}
If '$data(tRecordData(tCurrChunk, "block")) {
Set tCurrString = $piece(tRecordData(tCurrChunk), $char(44), tTopPiece)
}
Do ..checkMerge(.tCurrChunk, .tRecordData, .tCurrString, $char(44), .tTopPiece)
If pGetTopFields {
Set pObject.Test = tCurrString
}
If '$data(tRecordData(tCurrChunk, "block")) {
Set tCurrString = $piece(tRecordData(tCurrChunk), $char(44), tTopPiece)
}
Do ..checkMerge(.tCurrChunk, .tRecordData, .tCurrString, $char(44), .tTopPiece)
If pGetTopFields {
Set pObject.Organism = tCurrString
}
If '$data(tRecordData(tCurrChunk, "block")) {
Set tCurrString = $piece(tRecordData(tCurrChunk), $char(44), tTopPiece)
}
Do ..checkMerge(.tCurrChunk, .tRecordData, .tCurrString, $char(44), .tTopPiece)
If pGetTopFields {
Set pObject.Antibiotic = tCurrString
}
If '$data(tRecordData(tCurrChunk, "block")) {
Set tCurrString = $piece(tRecordData(tCurrChunk), $char(44), tTopPiece)
}
Do ..checkMerge(.tCurrChunk, .tRecordData, .tCurrString, $char(44), .tTopPiece)
If pGetTopFields {
Set pObject.AntibioticInterpretation = tCurrString
}
If '$data(tRecordData(tCurrChunk, "block")) {
Set tCurrString = $piece(tRecordData(tCurrChunk), $char(44), tTopPiece)
}
Do ..checkMerge(.tCurrChunk, .tRecordData, .tCurrString, $char(44), .tTopPiece)
If pGetTopFields {
Set pObject.Submitter = tCurrString
}
If '$data(tRecordData(tCurrChunk, "block")) {
Set tCurrString = $piece(tRecordData(tCurrChunk), $char(44), tTopPiece)
}
Do ..checkMerge(.tCurrChunk, .tRecordData, .tCurrString, $char(44), .tTopPiece)
If pGetTopFields {
Set pObject.ReqExtPatientID = tCurrString
}
Quit tStatus
}
XData RecordMap [ XMLNamespace = "http://www.intersystems.com/Ensemble/RecordMap" ]
{
<Record xmlns="http://www.intersystems.com/Ensemble/RecordMap" name="CUH.Recordmap.ENHSens2HL7" type="delimited" char_encoding="UTF-8" targetClassname="CUH.Recordmap.ENHSens2HL7.Record" padFromLeft="0" recordTerminator="\x0d\x0a" escaping="quote" escapeSequence=""">
<Separators>
<Separator>,</Separator>
</Separators>
<Field name="SpecimenID" required="0" datatype="%String"></Field>
<Field name="PatientSurname" required="0" datatype="%String"></Field>
<Field name="PatientFirstName" required="0" datatype="%String"></Field>
<Field name="DOB" required="0" datatype="%String"></Field>
<Field name="PatientNHSNumber" required="0" datatype="%String"></Field>
<Field name="MRN" required="0" datatype="%String"></Field>
<Field name="Collected" required="0" datatype="%String"></Field>
<Field name="Received" required="0" datatype="%String"></Field>
<Field name="Resulted" required="0" datatype="%String"></Field>
<Field name="Verified" required="0" datatype="%String"></Field>
<Field name="SpecimenType" required="0" datatype="%String"></Field>
<Field name="Source" required="0" datatype="%String"></Field>
<Field name="Test" required="0" datatype="%String"></Field>
<Field name="Organism" required="0" datatype="%String"></Field>
<Field name="Antibiotic" required="0" datatype="%String"></Field>
<Field name="AntibioticInterpretation" required="0" datatype="%String"></Field>
<Field name="Submitter" required="0" datatype="%String"></Field>
<Field name="ReqExtPatientID" required="0" datatype="%String"></Field>
</Record>
}
}Kind Regards
Stuart
Stuart Byrne | eHospital Senior Epic Interface & Environment Systems Analyst |
Cambridge University Hospitals NHS Foundation Trust | Box 117 |
Ext: 58365 Direct Dial: 01223 348365
This email is confidential, see www.cuh.org.uk/email_disclaimer.html
Annual Leave: 26/05 (Half Day), 02/06, 05/06, 12/06, 12/07 – 28/07
Comments
Hi Stuart,
Are you writing your own business service?
Have you looked at EnsLib.RecordMap.Service.FTPService , which Ensemble includes out of the box? Maybe it does everything you need.
Best Regards,
David
Thanks David. This worked really well and I was able to call my record map and pass to a BP router.
In the meantime I got my stream to work, but the EnsLib.RecordMap.Service.FTPService is more straightforward and will be supported in future upgrades.