go to post Ashok Kumar T · Oct 13 Hi @Lucrezia Puntorieri Yes you can create a method and classmethod programmatically. Set clsmethodObj = ##class(%Dictionary.MethodDefinition).%New() Set clsmethodObj.Name="TestClsMethod" Set clsmethodObj.ClassMethod=1 Do clsmethodObj.Implementation.WriteLine($C(9)_"Set ^test=""Test"" ") Do clsmethodObj.Implementation.WriteLine($C(9)_"Quit ^test ") Set methodObj = ##class(%Dictionary.MethodDefinition).%New() Set methodObj.Name="TestMethod" Set methodObj.ClassMethod=0 Do methodObj.Implementation.WriteLine($C(9)_"For I=1:1:10 { S ^test(i)=i} ") Do methodObj.Implementation.WriteLine($C(9)_"Quit ^test ") Do clsObj.Methods.Insert(clsmethodObj) Do clsObj.Methods.Insert(methodObj)
go to post Ashok Kumar T · Oct 11 Hi Jack IRIS does not provide built-in functionality to generate classes directly from a JSON Schema, unlike the support available for XML Schema (XSD). However, you can programmatically create and compile classes at runtime using the %Dictionary.ClassDefinition API. Here is the sample code to generate a class. ClassMethod CreateClass() { Set clsObj = ##class(%Dictionary.ClassDefinition).%New() Set clsObj.Name="Test.NewClass" Set clsObj.Super="%RegisteredObject,%JSON.Adaptor" Set clsObj.Description="Class created via code" Set clsObj.DdlAllowed = 1 Set clsObj.Inheritance="left" Set propObj = ##class(%Dictionary.PropertyDefinition).%New() Set propObj.Name="Name" Set propObj.Type="%String" Set propObj.SqlColumnNumber=2 Do propObj.Parameters.SetAt(70,"MAXLEN") Set indexObj = ##class(%Dictionary.IndexDefinition).%New() Set indexObj.Name="NameIdx" Set indexObj.Properties="Name" Do clsObj.Properties.Insert(propObj) Do clsObj.Indices.Insert( indexObj) Set st= clsObj.%Save() D $SYSTEM.OBJ.Compile("Test.NewClass","ckb") If $$$ISERR(st) w $SYSTEM.OBJ.DisplayError(st) }
go to post Ashok Kumar T · Sep 28 Hello @Julius Kavay Thanks for pointing that out — you're absolutely right. The generator method for property initialization is missing. However, we are able to create an instance of %CSP.Page
go to post Ashok Kumar T · Sep 3 Hi @Touggourt Use can use _ToJSON() or toJson() instead of %ToJSON()Embedded python post for more information
go to post Ashok Kumar T · Jul 21 You can use the Log() method or do LOG^%ETN(ErrorMessage) inside the Try{} Catch ex{} block and routine to capture the error on Application Errors.
go to post Ashok Kumar T · Jul 17 Hello @PhoebeK If emailAttachmentList is a DynamicArray, then the following property declaration is correct: Attempt 2 // Property emailAttachmentList As List of Request.EmailAttachment(%JSONFIELDNAME = "emailAttachmentList"); It looks like you're trying to set the value directly like: callrequest.emailAttachmentList.attachmentClass = "application/xml" However, since emailAttachmentList is a list, you need to either:- Use %JSONImport(response) to populate the list properly (e.g., `callrequest.%JSONImport(response)`), or- Loop through the list and set the property on each individual item, like this: For i=1:1:callrequest.emailAttachmentList.Count() { Set callrequest.emailAttachmentList.GetAt(i).attachmentClass = "application/xml" }
go to post Ashok Kumar T · Jul 11 Hello @Scott Roth I hope the target is a object reference of HS.FHIRModel.R4.Patientand the "name" property in in R4.Patient is an object property(HS.FHIRModel.R4.SeqOfHumanName ) and thisSeqOfHumanName stores the %DynamicArray of HS.FHIRModel.R4.HumanName object values into property called "list" So, First we have to check the name is $IsObject(r4Patient.name)&&(r4Patient.name.%IsA("HS.FHIRModel.R4.SeqOfHumanName")) and if it's true you can iterate the list (%DynamicArray) Set iter = r4Patient.name.list.%GetIterator() You can directly copy and run this example directly and it works for me. ClassMethod ParseHumanName() { Set r4Patient = ##class(HS.FHIRModel.R4.Patient).%New() ; Set seqHuman = ##class(HS.FHIRModel.R4.SeqOfHumanName).%New() ; create human name for seqHuman Set human = ##class(HS.FHIRModel.R4.HumanName).%New() Set human.family="pil" Set human.text="Ashok,kumar" ; ;push the HumanName into SeqOfHumanName Do seqHuman.add(human) ; Set SeqOfHumanName into Patient.name Set r4Patient.name = seqHuman If $IsObject(r4Patient.name)&&(r4Patient.name.%IsA("HS.FHIRModel.R4.SeqOfHumanName")) { Set iter = r4Patient.name.list.%GetIterator() #; while iter.%GetNext(,.humanName) { zw humanName.toDao() } } quit }
go to post Ashok Kumar T · Jul 8 The HS.FHIRModel.R4.Patient class in IRIS directly represents the FHIR R4 Patient resource as defined. When a FHIR Bundle is loaded using HS.FHIRModel.R4.Bundle.fromDao(), each resource in the bundle's entry.resource is automatically mapped to the correct HS.FHIRModel.R4.* subclass (e.g., Patient, Encounter, AllergyIntolerance) based on its resourceType. There’s no need for manual casting — the object model handles the typing internally. here is the sample code Set bundle={"resourceType":"Bundle","type":"searchset","total":3,"entry":[{"fullUrl":"https://example.org/fhir/Patient/patient-1","resource":{"resourceType":"Patient","id":"patient-1","name":[{"family":"Doe","given":["John"]}],"gender":"male","birthDate":"1985-02-15"},"search":{"mode":"match"}},{"fullUrl":"https://example.org/fhir/Encounter/encounter-1","resource":{"resourceType":"Encounter","id":"encounter-1","status":"finished","class":{"system":"http://terminology.hl7.org/CodeSystem/v3-ActCode","code":"AMB","display":"ambulatory"},"subject":{"reference":"Patient/patient-1"},"period":{"start":"2023-07-01T10:00:00Z","end":"2023-07-01T10:30:00Z"}},"search":{"mode":"include"}},{"fullUrl":"https://example.org/fhir/AllergyIntolerance/allergy-1","resource":{"resourceType":"AllergyIntolerance","id":"allergy-1","clinicalStatus":{"coding":[{"system":"http://terminology.hl7.org/CodeSystem/allergyintolerance-clinical","code":"active"}]},"verificationStatus":{"coding":[{"system":"http://terminology.hl7.org/CodeSystem/allergyintolerance-verification","code":"confirmed"}]},"type":"allergy","category":["food"],"criticality":"high","code":{"coding":[{"system":"http://snomed.info/sct","code":"227493005","display":"Cashew nuts"}],"text":"Allergy to cashews"},"patient":{"reference":"Patient/patient-1"},"reaction":[{"manifestation":[{"coding":[{"system":"http://snomed.info/sct","code":"271807003","display":"Skin rash"}]}],"severity":"moderate"}]},"search":{"mode":"include"}}]} set fhirModelBundle = ##class(HS.FHIRModel.R4.Bundle).fromDao(bundle) ; Zwrite fhirModelBundle.entry.list.size() 3 ; Zwrite fhirModelBundle.entry.list.get(0).toDao() ; patient {"fullUrl":"https://example.org/fhir/Patient/patient-1","resource":{"resourceType":"Patient","id":"patient-1","name":[{"family":"Doe","given":["John"]}],"gender":"male","birthDate":"1985-02-15"},"search":{"mode":"match"}} ; <DYNAMIC OBJECT> ; Zwrite fhirModelBundle.entry.list.get(1).toDao() ; encounter {"fullUrl":"https://example.org/fhir/Encounter/encounter-1","resource":{"resourceType":"Encounter","id":"encounter-1","status":"finished","class":{"system":"http://terminology.hl7.org/CodeSystem/v3-ActCode","code":"AMB","display":"ambulatory"},"subject":{"reference":"Patient/patient-1"},"period":{"start":"2023-07-01T10:00:00Z","end":"2023-07-01T10:30:00Z"}},"search":{"mode":"include"}} ; <DYNAMIC OBJECT> ; Zwrite fhirModelBundle.entry.list.get(2).toDao() ; Allergy {"fullUrl":"https://example.org/fhir/AllergyIntolerance/allergy-1","resource":{"resourceType":"AllergyIntolerance","id":"allergy-1","clinicalStatus":{"coding":[{"system":"http://terminology.hl7.org/CodeSystem/allergyintolerance-clinical","code":"active"}]},"verificationStatus":{"coding":[{"system":"http://terminology.hl7.org/CodeSystem/allergyintolerance-verification","code":"confirmed"}]},"type":"allergy","category":["food"],"criticality":"high","code":{"coding":[{"system":"http://snomed.info/sct","code":"227493005","display":"Cashew nuts"}],"text":"Allergy to cashews"},"patient":{"reference":"Patient/patient-1"},"reaction":[{"manifestation":[{"coding":[{"system":"http://snomed.info/sct","code":"271807003","display":"Skin rash"}]}],"severity":"moderate"}]},"search":{"mode":"include"}} ; <DYNAMIC OBJECT>
go to post Ashok Kumar T · Jun 25 Index ZipIDX On ZipCode [ Data = (City, State) ]; Here, the index is built on the ZipCode field, and the City and State fields are included in the Data portion of the index structure (i.e., stored as part of the index global). When a query retrieves only City and State based on a ZipCode filter, the SQL engine can perform an index-only scan and avoid accessing the main "Master map". This behavior is similar to a covering index in SQL databases because the requested data is fully available within the index itself. SELECT City, State FROM Sample.Person WHERE ZipCode = 19904; In this case, the index global might look like: ^gblI("ZipIDX", ZipCode, ID) = $LB("", City, State) The query will be satisfied using just the index, avoiding a full table (master map) access. However, this index does not provide any benefit when the query uses City or State as filter conditions, since those fields are not part of the index key. So, It will search on the "Master map" Now, consider another index: Index CityStateIDX On (City, State); This is a composite index (or multi-column index), where both City and State are stored as part of the index key (subscripts), not as index data. The global would look like: ^gblI("CityStateIDX", City, State, ID) = " SELECT state FROM SAMPLE.PERSON1 WHERE city ='Newton' When a query uses City or State in the WHERE clause, the index is used to locate the matching IDs, but the SQL engine must then perform a lookup in the master map to fetch any other columns, even if you're selecting only indexed fields like City or State. So, composite indexes help filter rows efficiently, but they don't function like covering indexes unless the query involves only index keys and you don't need to retrieve other columns. Here is the Index types documentation
go to post Ashok Kumar T · Jun 11 The issue is caused by the PythonRuntimeLibrary not being configured. Starting from version 2024.2, Python is no longer bundled with IRIS due to the introduction of the Flexible Python Runtime feature. As a result, the Python directory is missing, preventing the installation of the Wheel file. Check this post about this configuration.
go to post Ashok Kumar T · Jun 3 You can delete the application error logs for all days by executing the below code for specific namespace ClassMethod DeleteAppErrorLog(Namespace As %String = {$Namespace}) As %Status { New $Namespace Set $Namespace = "%SYS" Return ##class(SYS.ApplicationError).DeleteByNamespace(Namespace) } Delete by date ClassMethod DeleteAppErrorLogByDT(pNamespace As %String = {$Namespace},pDate ={$ZD(+$H)}) As %Status { New $Namespace Set $Namespace = "%SYS" Return ##class(SYS.ApplicationError).DeleteByDate(pNamespace,pDate) }
go to post Ashok Kumar T · May 13 Maybe can you try to wrap the HL7 message like below format and set the ContentType As "application/xml" in additional setting in the Business operation "EnsLib.HL7.Operation.HTTPOperation" and check for the response headers as well if required. <?xml version="1.0" encoding="UTF-8"?> <HL7Message> <![CDATA[ MSH|^~\&|... your message ... PID|... etc ... ]]> </HL7Message>
go to post Ashok Kumar T · May 9 We can use the %IsDefined method to check the key is defined, and %Size() to determine the number of the elements in an Object or Array. These methods help to prevent from the <INVALID OREF> and <UNDEFINED> // verify the "items" is present and it has values If responseData.%IsDefined("items")&&(responseData.items.%Size()) { Set item1 = responseData.items.%Get(0) If $IsObject(item1) { Write item1.portalUrl } /*another*/ If $IsObject(item1)&&(item1.%IsDefined("portalUrl")) { Write item1.portalUrl } } The %GetTypeOf method is used to determine the type of a key, and it returns 'unassigned' if the key does not exist If responseData.%GetTypeOf("items")="array" { Set item1 = responseData.items.%Get(0) If $IsObject(item1) { Write item1.portalUrl } }
go to post Ashok Kumar T · Apr 29 Hi @Pravin Barton The {Contents} has the id of the stream property. So, We can open the the stream object by using OID and then convert to JSON like below. and the stream write need to use %ToJSON() for JSON serialization stream.Write({"msg":"hello world!"}.%ToJSON()) Trigger ExtractKeys [ Event = INSERT/UPDATE, Foreach = row/object, Time = AFTER ] { new contentsJSON, id, msg if {Contents*C} { set contentsJSON = {}.%FromJSON(##class(%Stream.GlobalCharacter).%Open($lb({Contents},"%Stream.GlobalCharacter","^PAB.DebugStreamS"))) set id = {ID} set msg = contentsJSON.msg &sql(update learn_Smp.NewClass13 set msg = :msg where Id = :id) $$$ThrowSQLIfError(SQLCODE, %msg) } } Thanks!
go to post Ashok Kumar T · Apr 11 Hi @Julian Matthews The Ens.StreamContainer class is a %Persistent class and it stores the different types of stream in it. So, If you delete the row/record by id / or by query it will delete the entry as well as the stream contents(it's also part of the row) from the Ens.StreamContainer table. So, be cautious before deleting the container. %OnDelete callback method is used to do some additional function while deleting the object.
go to post Ashok Kumar T · Mar 31 Hello @Nezla, The %SYS.Task class has the task details which includes the status of the task. The "Suspended" column has value if incase the task is errored out while running ("Suspend Leave" ) or the task is suspended ("Suspend Reschedule"). Based on this column you can find out the suspended /errored task. Use the below query for the TaskName and additional details. select Name,Status,TaskClass,Suspended from %SYS.Task
go to post Ashok Kumar T · Mar 28 You can use $$$CurrentMethod from Ensemble.inc used to get the current classmethod in your methods.
go to post Ashok Kumar T · Mar 27 Hello @Michael Wood, here are several approaches you can take to handle this. One option is to create a file service that reads the file as a stream and sends it to a custom business process. You can then convert that stream into a JSON object and iterate through each DynamicObject entry. Alternatively, you could send the stream to BPL and process the JSON there Simplified sample of process the JSON. Class Samples.Introp.JSONFileService Extends Ens.BusinessService { Parameter ADAPTER = "EnsLib.File.InboundAdapter"; Method OnProcessInput(pInput As %Stream.Object, Output pOutput As %RegisteredObject) As %Status { Do ..SendRequestSync("JSONFileProcess",pInput,pOutput) Quit $$$OK } } Class Samples.Introp.JSONFileProcess Extends Ens.BusinessProcess [ ClassType = persistent ] { Method OnRequest(pRequest As Ens.Request, Output pResponse As Ens.Response) As %Status { Set json = {}.%FromJSON(pRequest) Set iter = json.%GetIterator() while iter.%GetNext(.key,.val) { s ^test($Classname(),$NOW(),key)=val.%ToJSON() } Quit $$$OK } } Thanks!
go to post Ashok Kumar T · Mar 5 Hello @Krishnaveni Kapu %SYS.Task is responsible for store, suspend and resume for all the tasks. so, your can execute the below method programmatically to achieve it. It expects the task id as the first argument You can execute the below query to get the task id, name and additional information select Suspended,Name,id from %SYS.Task suspend Flag 1 - Suspend the task, but leave it in task queue (default)2 - Suspend the task, remove from task queue, and reschedule for next time Set taskId = 1001 Set flag = 2 Write ##class(%SYS.Task).Suspend(taskId,flag) resume Set taskId=1001 Write ##class(%SYS.Task).Resume(taskId)