go to post Enrico Parisi · Jan 19 Suppose you have your JSON in a stream StreamFHIR, then: Set BundleObject=##class(HS.FHIR.DTL.vR4.Model.Resource.Bundle).FromJSON(StreamFHIR,"vR4") If you want ONLY the first entry, then: Set FirstEntry=BundleObject.entry.GetAt(1)
go to post Enrico Parisi · Jan 18 First I'd suggest not to use a persistent class "linked" to a message (Ens.Response in this case), Supplier is linked by your message class in this case.If you do it, you will definitely create "orphaned" persistent objects when you purge, unless you add some logic (like triggers and callbacks) to delete the "linked" persistent objects when a message is purged. To avoid this (when possible) a serial class is preferred. So, the Supplier class would be: Class Community.App.Msg.Supplier Extends (%SerialObject, %XML.Adaptor) { Property row As %Integer; } As for the message class: Class Community.App.Msg.Suppliers Extends Ens.Response { Property Supplier As list Of Community.App.Msg.Supplier(XMLPROJECTION = "ELEMENT"); ClassMethod test() As %Status { set XmlString="<Suppliers><Supplier><row>1</row></Supplier><Supplier><row>2</row></Supplier></Suppliers>" set reader = ##class(%XML.Reader).%New() $$$ThrowOnError(reader.OpenString(XmlString)) do reader.CorrelateRoot("Community.App.Msg.Suppliers") do reader.Next(.Suppliers, .tSC) do Suppliers.XMLExport(,",indent") quit tSC } } For simplicity I modified the sample to be a classmethod.When the test() method is run the output is: EPTEST>d ##class(Community.App.Msg.Suppliers).test() <Suppliers> <Supplier> <row>1</row> </Supplier> <Supplier> <row>2</row> </Supplier> </Suppliers> The relevant documentation is "Controlling the Form of the Projection for Collection Properties" here. Let me add a few notes. If a class extend Ens.Response or Ens.Request is not necessary to extend %Persistent because is already inherited by Ens.Request/Ens.Response.Edit: please see Antoine commnet below If the desired XML tag correspond to the class name (without package), it is not necessary to add the XMLNAME parameter, like you did in App.Objects.Suppliers class. Same goes for XMLNAME property parameter XMLNAME = "row" is not necessary because the property name correspond to the desired XML tag name.
go to post Enrico Parisi · Jan 15 Optionally, instead of using IgnoreNull property of the reader, add to your M.PAT class: Parameter XMLIGNORENULL = 1;
go to post Enrico Parisi · Jan 15 Please check the documentation here regarding the IgnoreNull property of the reader.
go to post Enrico Parisi · Jan 14 OK, I think I understand the question! 😊 Suppose you want to put the "source" HL7 Message SourceConfigName in MSH:Security: <assign value='##class(Ens.MessageHeader).%OpenId($$$JobCurrentHeaderId).SourceConfigName' property='target.{MSH:Security}' action='set' /> In case you what to get the first message source config name: <assign value='##class(Ens.MessageHeader).%OpenId($$$JobSessionId).SourceConfigName' property='target.{MSH:Security}' action='set' />
go to post Enrico Parisi · Jan 11 To "capture" output I'd use a pipe instead of $ZF(-100), here a code sample: Class Community.ExecOS [ Abstract ] { /// run an operating system command ClassMethod ExecOS(cmd As %String, Output LinesOut As %String) { set oldzeof=$SYSTEM.Process.SetZEOF(0) set io=$IO,LinesOut=0 try { if cmd="" Quit open cmd:"Q" use cmd for LinesOut=1:1 { read LinesOut(LinesOut) } } catch CatchError { If CatchError.Name'="<ENDOFFILE>" { set LinesOut=CatchError.Name } } close cmd Do $SYSTEM.Process.SetZEOF(oldzeof) Use io quit } } EPTEST>d ##class(Community.ExecOS).ExecOS("dir",.out) EPTEST>zw out=13 out(1)=" Volume in drive C has no label." out(2)=" Volume Serial Number is 3E11-87B5" out(3)="" out(4)=" Directory of c:\intersystems\irishealth\mgr\eptest" out(5)="" out(6)="02.01.2024 12:14 <DIR> ." out(7)="02.01.2024 12:14 <DIR> .." out(8)="11.01.2024 19:04 429'916'160 IRIS.DAT" out(9)="05.01.2024 14:26 42 iris.lck" out(10)="24.11.2023 00:34 <DIR> stream" out(11)=" 2 File(s) 429'916'202 bytes" out(12)=" 3 Dir(s) 63'936'786'432 bytes free" EPTEST>
go to post Enrico Parisi · Dec 28, 2023 It's a bug, I've created an issue in github with a possible fix.
go to post Enrico Parisi · Dec 27, 2023 At the moment IRIS does not support OpenAPI 3.0, the project OpenAPI-Suite in Open Exchange ("Set of tools for ObjectScript code generation from Swagger 3.0") support it.
go to post Enrico Parisi · Dec 27, 2023 I found the problem. The issue does not happen if the service user is changed using: IRISinstall.exe setserviceusername <instance-name> <username> <password> When that command is issued two groups are created: IRISServicesIRIS_Instance_<InstanceNme> and the service user is added as member of there two groups. The reason that it works using this way is that to the IRISServices group, in Local Security Policy is assigned the "Replace a process level token" user right. In other words, the user that stars IRIS need the "Replace a process level token" right assigned via Local Security Policy (or GPO in an AD Domain). Lesson learned:- Use IRISinstall.exe to change the user for the IRIS serviceor- Assign "Replace a process level token" right to the user of IRIS service
go to post Enrico Parisi · Dec 17, 2023 Set sc=##class(%File).GetDirectorySpace("D:",.FreeSpace) Write FreeSpace Classreference: classmethod GetDirectorySpace(Name As %String, ByRef FreeSpace As %String, ByRef TotalSpace As %String, Flag As %Integer = 1) as %StatusReturn the amount of total space and free space in either Bytes,MB,GB on a drive or directoryName = Valid Drive or directory specificationFlag = 0 - Return bytesFlag = 1 - Return MB (Default)Flag = 2 - Return GB MB and GB returned are rounded to 2 decimal places.Any error status returned is O/S level error. Note that on Windows only drives have a measurement for free space and directories can not so the FreeSpace is only returned for drives.
go to post Enrico Parisi · Dec 14, 2023 Please note that "%PosixTime values have a 1 microsecond resolution", see %Library.PosixTime class reference documentation. Then:USER>set ts="2023-12-12 19:46:19.000" USER>set Posix=##class(%Library.PosixTime).TimeStampToLogical(ts) USER>write ##class(%Library.PosixTime).LogicalToTimeStamp(Posix-18000000000)2023-12-12 14:46:19 Enrico
go to post Enrico Parisi · Dec 12, 2023 Using correct length of 16 characters for IV and 32 characters key. This Javascript: var iv = CryptoJS.enc.Hex.parse("00000000000000000000000000000000");var stringyouWantToEncrypt = "HelloWorld";var base64Key = "RXJjb2xpbm9zZW1wcmVpbnBpZWRpMDEyMzQ1Nzg5MDE=";var encrypted = CryptoJS.AES.encrypt( stringyouWantToEncrypt, CryptoJS.enc.Base64.parse(base64Key), { iv: iv, }) And this ObjectScript: Set text="HelloWorld"Set IV=$c(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)Set KEY = "RXJjb2xpbm9zZW1wcmVpbnBpZWRpMDEyMzQ1Nzg5MDE="Set KEY=$SYSTEM.Encryption.Base64Decode(KEY)Set text=$ZCONVERT(text,"O","UTF8")Set sCrypt=$SYSTEM.Encryption.AESCBCEncrypt(text,KEY,IV)Set sToken=$SYSTEM.Encryption.Base64Encode(sCrypt)Write !,!, "Encoded -> "_sToken Both return the same: Encoded -> 2s4qbUJC6romvsp7TP2L4A== Enrico
go to post Enrico Parisi · Dec 8, 2023 Use foreach action to loop DRGgrp() and inside the loop insert an if action to the check if = "PMP", use break action when found. If you need more detail, provide a sample HL7 message and specify what you need to do after finding it. Enrico
go to post Enrico Parisi · Dec 8, 2023 Use foreach action to loop DRGgrp() and inside the loop insert the check. Enrico
go to post Enrico Parisi · Dec 7, 2023 I don't think you can implement it in a messaging routing rule. Personally I would implement it using code, writing a Business Process class. Another option is using a BPL business process, but I'm not a fan of BPL. But probably that's just me. 😊 Enrico
go to post Enrico Parisi · Dec 6, 2023 I would create my "custom" datatype extending %Library.DateTime: Class Community.dt.CustomDateTime Extends %Library.DateTime { ClassMethod LogicalToXSD(%val As %TimeStamp) As %String [ ServerOnly = 1 ] { Set %val=##class(%Library.TimeStamp).LogicalToXSD(%val) Quit $translate(%val,"TZ"," ") } ClassMethod XSDToLogical(%val As %String) As %TimeStamp [ ServerOnly = 1 ] { Set $e(%val,11)="T" Quit ##class(%Library.TimeStamp).XSDToLogical(%val) } } Then in your class define your property as: Property OPDT As Community.dt.CustomDateTime; Are you sure you really need %Library.DateTime and not %Library.TimeStamp?The difference is the JDBC/ODBC format. From the documetation: %DateTime is the same as %TimeStamp (is a sub-class or %TimeStamp) with extra logic in the DisplayToLogical and OdbcToLogical methods to handle imprecise datetime input T-SQL applications are accustomed to. If you prefer using %Library.TimeStamp, then change the superclass in my sample code. After that: USER>Set reader = ##class(%XML.Reader).%New() USER>Set sc=reader.OpenString("<NewClass2><OPDT>2023-11-30 11:07:02</OPDT></NewClass2>") USER>Do reader.CorrelateRoot("Samples.NewClass2") USER>Do reader.Next(.ReturnObject,.sc) USER>Do ReturnObject.XMLExport(,",indent") <NewClass2> <OPDT>2023-11-30 11:07:02</OPDT> </NewClass2> USER>Write ReturnObject.OPDT 2023-11-30 11:07:02 USER> Enrico