On the other hand, I just tested both cases in Firefox using JSON.parse() and they both fail. Browsers tend to be pretty tolerant of bad stuff, so the fact that Firefox won't accept trailing commas makes a good case for IRIS not allowing trailing commas either.
Since this is the syntax for a "JSON literal", and only happens in ObjectScript code, it makes sense to me that IRIS would force the developer to do the right thing.
%FromJSON has to deal with JSON that comes from other sources, so it makes sense that it is more forgiving of bad practices.
File Specs for services support wildcards, but not the complex time stamp specifications that are used for outputting filenames from an operation.
File Spec Filename or wildcard file specification for file(s) to retrieve. For the wildcard specification, use the convention that is appropriate for the operating system on the local InterSystems IRIS Interoperability machine.
I haven't tested the code below, but in your subclass you can override MakeRequest(), call the original superclass version of MakeRequest() and then you should be able to set the header before returning from your custom method.
Something like this:
Method MakeRequest(pRequestMethod As %String, pPayload, pRequestPath As %String, pQueryString As %String, ByRef pHeaders) As %RegisteredObject
{
set ..%HttpRequest = ##super(pRequestMethod, pPayload, pRequestPath, pQueryString, .pHeaders)
do ..%HttpRequest.SetHeader("Some Header Name", "Some Header Value")
return ..%HttpRequest
}
Since you mention Clinical Viewer I assume you're talking about HealthShare and not about TrakCare. HealthShare includes documentation on customizing the Clinical Viewer here:
I agree with Vic that this is probably not worth the complexity. The rule definitions are stored as XML -- to change them you'll need to fetch the XML, modify it, then save the changed XML and re-compile the class. It would look something like this:
set tMyRuleClassName="My.RoutingRuleClass"
&SQL(select %id into :tXDataID from %Dictionary.XDataDefinition where parent = :tMyRuleClassName and Name='RuleDefinition')
if (SQLCODE > 0) {
// Query returned no results. Do some error handling
quit
}
set tRuleDefinition=##class(%Dictionary.XDataDefinition).%OpenId(tXDataID)
/* This stream contains the raw XML of the RuleDefinition. It looks like this:
<ruleDefinition alias="" context="EnsLib.HL7.MsgRouter.RoutingEngine" production="TESTINGPKG.FoundationProduction">
<ruleSet name="" effectiveBegin="" effectiveEnd="">
<rule name="">
<when condition="1">
<send transform="" target="HL7.File.Out"/>
<return/>
</when>
</rule>
</ruleSet>
</ruleDefinition>
*/
set tRuleDefinitionXMLStream=##class(%Stream.GlobalCharacter).%New()
do tRuleDefinitionXMLStream.CopyFrom(tRuleDefinition.Data)
// Use XML classes to manipulate the stream
// (docs about XML classes: https://docs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page.cls?KEY=GXML_intro)
// ...
// ...
// ...
// Ok, done making changes to the stream
// Copy the changed XML back into the RuleDefinition
do tRuleDefinition.Data.CopyFrom(tRuleDefinitionXMLStream)
// Save the changees to the rule definition XData
set tSC=tRuleDefinition.%Save()
// Check if tSC indicates an error and do something about it
if $$$ISERR(tSC) {
// Do some error handling
}
// Recompile the rule class
set tSC=$System.OBJ.Compile(tMyRuleClassName,"cuk",.errorlog,1)
// Check if tSC indicates an error and do something about it
if $$$ISERR(tSC) {
// Do some error handling
}
You can definitely do the OAuth requests using basic HTTP calls.
Doing it in OnInit won't work because the token you receive has an expiration time.
You'll need to: - For every message your Operation receives you'll need to check if the cached token's expiration time has passed (or if there's no cached token). - If you need a new token, do your POST call to get a new token and cache it.
You'll probably want to check with the vendor to confirm where they expect to see it. One possibility is to pass it to GetAccessTokenClient as a property.
Here's a cheat sheet I put together on creating an OAuth client definition:
Go to System Administration >> Security >> OAuth 2.0 >> Client
Choose “Create Server Description”
Enter the endpoint URL provided for the OAuth server and select the TLS config you created for the OAuth server. Click “Discover and Save”. It should populate details about the OAuth server.
After saving, a new server entry will appear. Click “Client Configurations” and then “Create Client Configuration”
Enter the name details, select the TLS config, and choose Client Credentials as the grant type. The redirect URL won’t actually be used, but you’ll need to enter something for hostname anyway.
Keep track of what you enter for “Application Name”. You’ll need to put this in your custom code.
Switch to the “Client Credentials” tab and enter the Client ID and Client Secret you were given.
go to post
The HL7 organization offers training:
http://www.hl7.org/training/index.cfm
And there are other organizations that offer HL7 classes as well:
https://www.pathlms.com/hl7/courses/8159
I haven't taken these courses myself so I can't say if these are good or not.
go to post
If there aren't any delimiters in your input string, then this will do it:
Output:
go to post
[1,2,,3] is arguably more ambiguous than a trailing comma, and there are some precedents for (if and) how to treat trailing commas.
On the other hand, I just tested both cases in Firefox using JSON.parse() and they both fail. Browsers tend to be pretty tolerant of bad stuff, so the fact that Firefox won't accept trailing commas makes a good case for IRIS not allowing trailing commas either.
Strangely, Firefox apparently allows trailing commas in JavaScript, but not in JSON.
go to post
set obj1={"Value":123, } --> gives a SYNTAX
Since this is the syntax for a "JSON literal", and only happens in ObjectScript code, it makes sense to me that IRIS would force the developer to do the right thing.
%FromJSON has to deal with JSON that comes from other sources, so it makes sense that it is more forgiving of bad practices.
go to post
File Specs for services support wildcards, but not the complex time stamp specifications that are used for outputting filenames from an operation.
File Spec
Filename or wildcard file specification for file(s) to retrieve. For the wildcard specification, use the convention that is appropriate for the operating system on the local InterSystems IRIS Interoperability machine.
https://docs.intersystems.com/irisforhealthlatest/csp/docbook/Doc.View.c...
go to post
Have a look at the Record Mapper -- you can create a spec for your target flat file format, and then map to that as the target format in your DTL.
go to post
I haven't tested the code below, but in your subclass you can override MakeRequest(), call the original superclass version of MakeRequest() and then you should be able to set the header before returning from your custom method.
Something like this:
go to post
Is the problematic class particularly large?
go to post
Since you mention Clinical Viewer I assume you're talking about HealthShare and not about TrakCare. HealthShare includes documentation on customizing the Clinical Viewer here:
https://docs.intersystems.com/hs20211/csp/docbook/Doc.View.cls?KEY=HECUI
Note that you'll need to be a HealthShare customer to access this documentation.
go to post
I agree with Vic that this is probably not worth the complexity. The rule definitions are stored as XML -- to change them you'll need to fetch the XML, modify it, then save the changed XML and re-compile the class. It would look something like this:
go to post
I'm not aware of third-party widgets for ZEN Reports -- maybe someone else knows more.
Something else you could explore is generating SVG code to draw the graphic and output the SVG directly into an xsl-fo element using Zen Reports' <write>.
go to post
To get the gradient, you could assign a background image to a <container>.
go to post
If you control the DB schema, you can use triggers for this.
go to post
You can definitely do the OAuth requests using basic HTTP calls.
Doing it in OnInit won't work because the token you receive has an expiration time.
You'll need to:
- For every message your Operation receives you'll need to check if the cached token's expiration time has passed (or if there's no cached token).
- If you need a new token, do your POST call to get a new token and cache it.
go to post
You'll probably want to check with the vendor to confirm where they expect to see it. One possibility is to pass it to GetAccessTokenClient as a property.
https://docs.intersystems.com/irisforhealthlatest/csp/docbook/Doc.View.c...
Also, this sample assumes that they're using the client credentials grant type. This is the most likely option, but it would be worth confirming.
go to post
I like to use local multidimensional arrays as Dmitriy suggested.
Also, array objects are key/value based -- iterating through the keys always occurs in sorted order.
go to post
Here's a cheat sheet I put together on creating an OAuth client definition:
Go to System Administration >> Security >> OAuth 2.0 >> Client
Choose “Create Server Description”
Enter the endpoint URL provided for the OAuth server and select the TLS config you created for the OAuth server. Click “Discover and Save”. It should populate details about the OAuth server.
After saving, a new server entry will appear. Click “Client Configurations” and then “Create Client Configuration”
Enter the name details, select the TLS config, and choose Client Credentials as the grant type. The redirect URL won’t actually be used, but you’ll need to enter something for hostname anyway.
Keep track of what you enter for “Application Name”. You’ll need to put this in your custom code.
Switch to the “Client Credentials” tab and enter the Client ID and Client Secret you were given.
go to post
I think for Issuer endpoint you need to include the protocol:
https://api.veritystream.cloud/services/oauth
go to post
This snippet uses the built-in OAuth client to request a token and then add it to the HTTP header.
You'll need to configure an entry for the OAuth server with a sub-entry for this specific client:
https://docs.intersystems.com/healthconnectlatest/csp/docbook/Doc.View.c...
In the case of the sample code below, the client I configured is named TestClientA.
go to post
In your REST operation you can just do this. In this case the header name is "Authorization" but you can change it to whatever is required.