Globals are not my strongest suite... I am not sure how the data elements are stored in Globals. That said, I think I can answer your 2nd question. HealthShare will not store Allergies without AllergyCode. The SDA is actually only an intermediate format for the HealthShare Data Model; the data is stored in the Streamlet database on each Edge Gateway. You will get an Alert in your Ensemble Production; something like "An Allergy Code needed to store Allergy".

To answer your more general question, such as "How many patients are there with a specific Allergy Code?", I have to admit that HealthShare is quite poor for running report-style aggregated queries of type "select count(Patient), AllergyCode from ... group by AllergyCode". The Streamlets are stored as XML Objects with no discrete data fields and have to be loaded into memory using, for example, an API method LoadSDAObject(pStreamletId, ByRef pSDA) in the HS.SDA3.Streamlet.ContainerMethods class. pSDA would be your HS.SDA3.Allergy object. But these objects are of type %SerialObject, not %Persistent. Data for all patients on an Edge Gateway are typically stored in a single global ^HS.SDA3.Streamlet.AbstractD (you can use the System Explorer -> Globals browser to see how it looks). 

The only time I remember we needed to aggregate Patient/Encounter data we had to write custom code to pull it out of the global. And even after that, we had to transfer the data to a SQL server to run aggregated queries.

I think HealthInsight is a product where these aggregated queries are handled better.

I hope this helps.

Hi Ahmad, I believe this should work

Hi Ahmad,

Your added code seems correct. Except for the where you add the remainder to the newline... $PIECE(line"|", 8) gets the content of the 8th column. remainder begins with the content of the 9th column, without any separator between them. So maybe $PIECE(line"|", 8)_"^"_remainder or $PIECE(line"|", 8)_"|"_remainder if you want to keep the original separator between 8th and 9th columns.

Also I assume you have Set tLineNumber = 0 before the while loop. Then, set tLineNumber tLineNumber + 1 makes sense at the beginning of the loop (I usually initialize at 1 and would have the increment at the very end of the loop).

Also, SetPatientContact takes "line" by reference... I assume there is a reason for that... usually strings in COS can be passed by value... unless you are going to change it inside SetPatientContact; then it makes sense.

Hi Ahmad,

Maybe something like this?

Method SetEncounter(line, ByRef newLine, ByRef remainder, pFileType, pLineNumber) As %Status {

Set tSC = $$$OK

Set tNewField = ""

For i=2:1:$LENGTH(line) {

    Set word = $PIECE(line, "|", i)

    If i=2 {Set newField = word}

    Else {Set newField = newField_"^"_word}

    If i>8 Quit // If you don;t care what happens with columns 9 and after


Set remainder = $PIECE(line, "|", 9, $LENGTH(line))

Set newLine = tNewField_"^"_remainder

Quit tSC

// Here we go through the line by examining each field of your column, starting with column 2. So we just build your output with each iteration. You probably have to save your original line and and grab the remainder from it to concatenate with new line

I would also add better JSON support with %JSON.Adapter (the lack of which currently causes a lot of struggle for us on the older version)

I am seeing this in EnsLib.HPPT.InboundAdapter:

/// Set this property from onInit() in your Service class to make the adapter parse form variables from the form body in case of a form POST
Property ParseBodyFormVars As %Boolean;

So you just need to implement the OnInit() method as described here:

I realize that the docs provide very little... just looked through them myself. So I found more posts that you might find helpful:

I think the first post may be all you need... just put the upload part into the OnProcessnput() of your custom business service. You can also see similar code in the 2nd article, when you scroll to where it talks about form data.

Good luck!

Is your use case such that someone is posting data to your Server? If you use Ensemble, you probably benefit by reading:

If you use Cache Web Services and you are building a custom REST-based service, please read:

Basically, it sounds like you need to build REST-based Web Service that can receive http requests with attachments.  I assume that you already have a commercial Web Server (like Apache) where you can authenticate requests to your system and set up SSL certification if needed.

Hi Victor,

I assume that you need Dynamic Objects in order to create some JSON Output (so you can call %ToJSON() on the object to create a JSON string). So in my opinion, the complexity of your JSON object will drive these decisions - for example, how deeply nested will your JSON need to be?

From some familiarity with TextReader, it records every XML Element into a Property. So in theory, each Property can have its corresponding Dynamic Object which will be a Name/Value pair: Name = Name of Property; Value = Value of Property (i,e. XML Text Node)

It is hard to say more without seeing your XML structure or your JSON Spec. You may find the following links helpful:

Hi Virat,

If you are working in Cache, you can try to use Set tXMLList = $LISTFROMSTRING(a, "</RollNo>"). 

Then, iterate over the list:

while $LISTNEXT(tXMLList,ptr,value) {

    Set $P(value,">",*) = "***"


This pulls the last substring after ">" which would be your numerical value.

Hi Gevorg,

I had recently encountered a use case like yours where we needed to connect to an FTP server and retrieve files from it. We tried to used EnsLib.FTP.PassthroughService but found it impractical. The service performance was very slow and we would wait minute before the file was actually picked up. We ended up running a shell script that would connect to the FTP server, mget all of the files and copy them to a local directory where EnsLibFile.PassthroughService would take care of them.

I wonder whether you were able to resolve your problem with FTP?