Enrico Parisi · Jul 31, 2024 go to post

Set dynOBJ={}.%FromJSONFile("c:\temp\BundleSample.json")
Set firstResource=dynOBJ.entry.%Get(0).resource
Write firstResource.resourceType
 

Enrico Parisi · Jul 30, 2024 go to post

In the Management Portal go to Interoperability (choose namespace if asked) -> List -> Productions

There, do you see the production you need to open?
If yes, select the production line from the list and click the "Open" button below the title bar.

What do you get?

Enrico Parisi · Jul 26, 2024 go to post

USER>DO HELP^%G
 
The %G utility displays global nodes. A "?" at the "Global ^" prompt
displays the global directory. If you enter just the name of a global,
%G displays the entire global. You may also display a portion of the
global at different subscript levels or specific nodes.
 
A complete global reference, such as ^GLO(3,"BED",5) will display
only that particular node. You may specify a subtree, such as
^GLO(3,"BED", to display all descendants of that node. To display
both the node and its descendants, do not end your entry with a
comma or a right parenthesis.
 
You can leave a subscript field empty when you specify the subtree and
the %G utility displays any nodes matching the other subscripts:
^GLO(,"BED") will match any nodes with 'BED' as the second subscript.
 
You can specify a range of subscripts for a particular subscript
level by inserting a colon between the first and last subscript in the
range: ^PT(1,"ACC":"BIRTH"
 
You can use variables and simple expressions in a subscript
specification by assigning a value to the variable before calling %G.
For example SET ID=214 and enter something like ^PT(ID,0).

Enrico Parisi · Jul 26, 2024 go to post

You don't provide enough information to help you.

Can you please provide some more detail on how you are "reading" "message_code"?

What kind of object/class and how you load/populate  "response" when you mention "response.message_code"?

What product/version are you using?

Enrico Parisi · Jul 25, 2024 go to post

The RoutineList query in %Routine class does offer ranges, try this:

Set Query=##class(%Routine).RoutineListFunc("%D:%E")
Do Query.%Display()

Enrico
P.S.: Tested in latest IRIS, I'm not sure that the "Func" query method is available in 2017, but you can use your old %ResultSet with same parameters.

Enrico Parisi · Jul 18, 2024 go to post

It has happened to me a few time not having access to terminal (OS or IRIS).

For this situation I developed a quick and dirty CSP class to allow me to execute IRIS or OS commands.

Class SomePackege.Cmd Extends %CSP.Page
{

ClassMethod OnPage() As %Status
{
    &html<<html>
<head>
</head>
<body>
<form>
<input type="text" name="cmdOS" size="150" value='#(%request.Get("cmdOS"))#'>
<input type="submit" value="runOS" onclick="this.form.submitted.value=this.value;" >
<br/>
<input type="text" name="cmd" size="150" value='#(%request.Get("cmd"))#'>
<input type="submit" value="runCMD" onclick="this.form.submitted.value=this.value;" >
<input type="hidden" name="submitted">
</form>
>
    If (%request.Get("submitted")="runOS") && (%request.Get("cmdOS")'="") {
        Set cmdOS=%request.Get("cmdOS")
        Set io=$io
        Open cmdOS:"QR"
        Write "<tt>"
        Try {
            For  Use cmdOS Read line Use io Write $replace(..EscapeHTML(line)," ","&nbsp;"),"<br>"
        } Catch CatchError {
            Set sc=CatchError.AsStatus()
        }
        Use io Write "</tt>"
        Close cmdOS
        Use io
    } ElseIf (%request.Get("submitted")="runCMD") && (%request.Get("cmd")'="") {
        Set cmd=%request.Get("cmd")
        Write "<pre>"
        x cmd
        Write "</pre>"
    }
    &html<</body>
</html>>
    Quit $$$OK
}

}

Once the class is loaded (say, from Studio or VS code) in one namespace, just call it from the default csp/web application, for example:

http://yourhost:57772/csp/user/SomePackage.Cmd.cls

Please note that the UI is very, very, VERY rudimental (ugly), but gets the job done in case of need.

Enrico Parisi · Jul 4, 2024 go to post

I'm puzzled by the fact that the two $$$LOGINFO() are present in the trace when an exception should have raised BEFORE the $$$LOGINFO().

The code posted is not the code that generated that trace. And this is very confusing.

Maybe the code was modified without restarting the Business Operation?

Enrico Parisi · Jul 4, 2024 go to post

..Adapter.Credentials.Username and ..Adapter.Credentials.Password

Credentials property of EnsLib.FTP.InboundAdapter is %String, so I expect an <INVALID OREF> error.

In general, I'd suggest to put your code inside a Try/Catch, something like:

	Set sc=$$$OK
	Try {
	    
	    ; your code here
	    
	} Catch CatchError {
		#dim CatchError as %Exception.SystemException
		Set sc=CatchError.AsStatus()
	}
	Quit sc
Enrico Parisi · Jul 2, 2024 go to post

Just tested using IRIS for Health 2022.2 installed in a temp VM and it works fine.

Can you share the terminal output when you run that code?

Enrico Parisi · Jul 2, 2024 go to post

Did you try from terminal using the EXACT code I posted?

What product are you using? You mention "IRIS 2022.2" is it IRIS for Health?

Enrico Parisi · Jul 2, 2024 go to post

Using your code (simplified by me) from terminal it works fine using a sample CCDA from here.

set ccdaStream = ##class(%Stream.FileBinary).%OpenId("c:\temp\CCDA_CCD_b1_Ambulatory_v2.xml")
write "Size of CCDA Stream: ", ccdaStream.Size,!
set xsltTransform = "SDA3/CCDA-to-SDA.xsl"
set tTransformer = ##class(HS.Util.XSLTTransformer).%New()
set tSC = tTransformer.Transform(ccdaStream, xsltTransform, .sdaStream)
if 'tSC write "Transformation to SDA3 failed with error ",$system.Status.GetErrorText(tSC),!
set fhirStream = ##class(%Stream.TmpBinary).%New()
set SDA3ToFHIRObject = ##class(HS.FHIR.DTL.Util.API.Transform.SDA3ToFHIR).TransformStream(sdaStream, "HS.SDA3.Container", "R4")
if '$isobject(SDA3ToFHIRObject.bundle) write "Failed to transform SDA3 to FHIR",!
do SDA3ToFHIRObject.bundle.%ToJSON()

The result/output is a pretty long JSON FHIR bundle with CCDA data (I didn't check the content!)

Does your code works with that sample CCDA?

If not, then maybe there is something wrong in your CCDA.

For my test I used: IRIS for Windows (x86-64) 2024.1 (Build 267_2U) Tue Apr 30 2024 16:35:10 EDT

Enrico Parisi · Jun 28, 2024 go to post

You need to pass each argument separately, this will work:

d $ZF(-100,"/logcmd", "qpdf", "--encrypt", "test123", "test123", "256", "--", "C:\test\basement.pdf", "c:\test\basementenc.pdf") 

Enrico Parisi · Jun 28, 2024 go to post

I don't think the upgrade runs $System.OBJ.CompileAll() "automatically", it's your responsibility to recompile, if necessary.

Enrico Parisi · Jun 27, 2024 go to post

To my knowledge and (more importantly 😁) according to the documentation, it's not possible.

The types of the arguments in the subclass method must be consistent with the types of the arguments in the original method. Specifically, any given argument must be either the same as the original type or a subclass of the original type. 

The method in the subclass can have more arguments than the method in the superclass.

Note that in your case the problem is not the number of parameters/arguments, it's the type of the arguments that does not match the superclass %OnNew() (implemented in %Exception.AbstractException) arguments type:

Method %OnNew(pName As %String = "", pCode As %String = "", pLocation As %String = "", pData As %String = "", pInnerException As %Exception.AbstractException = {$$$NULLOREF}) As %Status [ Private ]

One option could be:

Class test.Foo Extends %Exception.AbstractException
{

Method %OnNew(arg1 As %String, arg2 As %String, arg3 As %String, arg4 As %String, pInnerException As %Exception.AbstractException = {$$$NULLOREF}, arg5 As %String) As %Status
{
        quit ##super("some message")
}

}
Enrico Parisi · Jun 27, 2024 go to post

%SYS>s db=##class(SYS.Database).%OpenId("C:\InterSystems\IRIS\mgr\user")
 
%SYS>w db.SFN
8
%SYS>

Enrico Parisi · Jun 27, 2024 go to post

Have you read the chapter "Purpose of System Default Settings" in the RIS documentation
page that @Vic Sun I linked in his post?

After reading the documentation, have you found the info you were looking for?

Enrico Parisi · Jun 26, 2024 go to post

Each DTL calls “ConstructClone” to make a copy of the message before making any changes to it. There will be hundreds of cloned-objects in case of hundreds of DTLs

Keep in mind that when you create a clone of an HL7 message using %ConstructClone() the segments ARE NOT CLONED.

Only modified segments will be replaced with the new modified segment content.
The storage of unmodified segments will be "shared" between the original HL7 message and the cloned message.

A little test do demonstrate it:

; open an existing message and see the storage
Set hl7msg=##class(EnsLib.HL7.Message).%OpenId(33)
zw ^EnsLib.H.MessageD(33)

^EnsLib.H.MessageD(33)=$lb("","","Demo.HL7.MsgRouter.Schema:ORM_O01",0,"2024-03-24 01:44:43.142","Demo.HL7.MsgRouter.Schema","C:\temp\hl7\in\XYZ1.txt"_$c(13,10)_" Document# 2, level 1, @Line 11","","",0)
^EnsLib.H.MessageD(33,"segs")=9
^EnsLib.H.MessageD(33,"segs",1)="8480,161"
^EnsLib.H.MessageD(33,"segs",2)="8480,162"
^EnsLib.H.MessageD(33,"segs",3)="8480,163"
^EnsLib.H.MessageD(33,"segs",4)="8480,164"
^EnsLib.H.MessageD(33,"segs",5)="8480,165"
^EnsLib.H.MessageD(33,"segs",6)="8480,166"
^EnsLib.H.MessageD(33,"segs",7)="8480,167"
^EnsLib.H.MessageD(33,"segs",8)="8480,168"
^EnsLib.H.MessageD(33,"segs",9)="8480,169"


; create a clone, save it and see the storage
Set hl7msgClone=hl7msg.%ConstructClone()
Write hl7msgClone.%Save()
Set CloneId=hl7msgClone.%Id()
zw ^EnsLib.H.MessageD(CloneId)

^EnsLib.H.MessageD(37)=$lb("","","Demo.HL7.MsgRouter.Schema:ORM_O01",1,"2024-03-24 01:44:43.142","Demo.HL7.MsgRouter.Schema","C:\temp\hl7\in\XYZ1.txt"_$c(13,10)_" Document# 2, level 1, @Line 11","","",0)
^EnsLib.H.MessageD(37,"segs")=9
^EnsLib.H.MessageD(37,"segs",1)="8480,161"
^EnsLib.H.MessageD(37,"segs",2)="8480,162"
^EnsLib.H.MessageD(37,"segs",3)="8480,163"
^EnsLib.H.MessageD(37,"segs",4)="8480,164"
^EnsLib.H.MessageD(37,"segs",5)="8480,165"
^EnsLib.H.MessageD(37,"segs",6)="8480,166"
^EnsLib.H.MessageD(37,"segs",7)="8480,167"
^EnsLib.H.MessageD(37,"segs",8)="8480,168"
^EnsLib.H.MessageD(37,"segs",9)="8480,169"

; as you can see the new cloned message shares exactly the same segments of the original HL7 message

; modify a segment in the cloned HL7 message, save it and see the storage

Write hl7msgClone.SetValueAt("NEWVALUE","MSH:3.1")
Write hl7msgClone.%Save()
zw ^EnsLib.H.MessageD(CloneId)

^EnsLib.H.MessageD(37)=$lb("","","Demo.HL7.MsgRouter.Schema:ORM_O01",1,"2024-03-24 01:44:43.142","Demo.HL7.MsgRouter.Schema","C:\temp\hl7\in\XYZ1.txt"_$c(13,10)_" Document# 2, level 1, @Line 11","","",0)
^EnsLib.H.MessageD(37,"UserValues")=""
^EnsLib.H.MessageD(37,"segs")=9
^EnsLib.H.MessageD(37,"segs",1)="8992,2"
^EnsLib.H.MessageD(37,"segs",2)="8480,162"
^EnsLib.H.MessageD(37,"segs",3)="8480,163"
^EnsLib.H.MessageD(37,"segs",4)="8480,164"
^EnsLib.H.MessageD(37,"segs",5)="8480,165"
^EnsLib.H.MessageD(37,"segs",6)="8480,166"
^EnsLib.H.MessageD(37,"segs",7)="8480,167"
^EnsLib.H.MessageD(37,"segs",8)="8480,168"
^EnsLib.H.MessageD(37,"segs",9)="8480,169"

; as you can see now the first segment is different, all other segments use the same storage as the original message

The storage and I/O overhead of the cloning performed by DTL is minimal and limited the the strictly necessary modifications.
Of course if you change all the segments content, then all segment will be replaced, there is no options, but more often than not, DTL modify a limited number of segments.

Enrico Parisi · Jun 25, 2024 go to post

ISO 8601 date format is not an accepted format for the SQL DATEPART function.

You can check the supported formats in the DATAPART SQL Documentation.

If I remove the trailing Z (for Zulu / UTC time) and leave the T, DatePart works fine

I'm afraid it does not woks fine:

select 'YEAR: '||DATEPART(YEAR,'2024-06-23T06:03:00') 

result:

YEAR: 1900

Try:

select 'YEAR: '||DATEPART(YEAR,$TRANSLATE('2024-06-23T06:03:00Z','TZ',' '))

Enrico Parisi · Jun 24, 2024 go to post

In my opinion, if you need to encode a file/stream "as is", without any conversion, so that the counterpart receiver get EXACTLY what your source file/stream is/was, then use %Stream.FileBinary.

If you need some character conversion (say, Unicode/UTF8 or others), then use %Stream.FileCharacter (with appropriate parameters...) that can handle the conversion.

Enrico Parisi · Jun 24, 2024 go to post

Why do you say the stream is typically a binary stream?

Because a Charecter Stream may introduce additional character set conversion.
In your case it seems your stream is a MS Word docx document file, that's a binary file (it's a zip file) and no character set conversion is needed nor wanted, you just take the "raw" content (i.e. binary content) and encode it in base64 when included in JSON/Dynamic Object.

Please note that the code:
Do obj.%Set("data",pStream,"stream>base64")

already encode the pStream content to base64! If you pass a base64 encoded stream, you'll end up with double base64 encoding!

Its' my understanding that all you need is to load a docx file into json/dynamiy object, then all you need is:

Set obj = {}
Set pFile = "/ICS/jira/wgetDATA1343.docx"
Set pStream = ##class(%Stream.FileBinary).%OpenId(pFile)
Do obj.%Set("data",pStream,"stream>base64")

The base64 encoding is performed using the "stream>base64" type parameter, here is the class reference documentation for the %Set() method.
This is much more efficient and easier to read.