Jeffrey Drumm · Jan 22, 2019 go to post

Your best option for doing this is to create a new HL7 TCPIP Service Class that extends EnsLib.HL7.Service.TCPService that overrides the OnConstructReply() Method. The example below includes the necessary code, along with the convenience of being able to adjust the MSH:7 date format by supporting the reconfiguration of the value of MSH7AckDateFormat in the Production's configuration panel for the service. It uses well-known strftime() formatting conventions.

This works with Ensemble version 2017.2.1:

ClassHICG.HL7.Service.TCPServiceExtendsEnsLib.HL7.Service.TCPService

{

/// Allows Customization of the date format used in the ACK's MSH:7 field. Uses C strftime() tokens to construct
/// the date in the desired format. Default is HL7 date/time format, yyyyMMddhhmmss.

PropertyMSH7AckDateFormatAs%String [ InitialExpression = "%Y%m%d%H%M%S" ];

ParameterSETTINGS = "MSH7AckDateFormat";

MethodOnConstructReply(OutputpReplyDocAsEnsLib.EDI.Document, pOriginalDocAsEnsLib.EDI.Document, ByRefpReplyCodeAs%String, ByRefpSCAs%Status, pEarlyAckAs%Boolean) As%Status

 {

       SetpReplyDoc=pOriginalDoc.NewReplyDocument(,..LocalFacilityApplication)

       SetpReplyDoc.Source=pOriginalDoc.%Id()

       Do:..#UseOriginalControlIdpReplyDoc.SetValueAt(pOriginalDoc.GetValueAt("1:10"),"1:10")

       DopReplyDoc.SetValueAt(##class(Ens.Util.Time).ConvertDateTime($H,"%q(3)",..MSH7AckDateFormat),"1:7")

       SettMSA=##class(EnsLib.HL7.Segment).%New($LB("",1))

       SettMSA.Separators=pReplyDoc.Separators

       DotMSA.SetValueAt("MSA",0)

       DotMSA.SetValueAt(pReplyCode,1)

       DotMSA.SetValueAt(pOriginalDoc.GetValueAt("1:10"),2)

       Do:$G($$$ExpectedSequenceNumber)tMSA.SetValueAt($$$ExpectedSequenceNumber,4)

       DopReplyDoc.AppendSegment(tMSA)

       SetpReplyDoc.IsMutable=0

       Quit$$$OK

 }

}

Jeffrey Drumm · Dec 14, 2018 go to post

There's also the ^DATABASE routine in %SYS for creating databases, but it provides no options for creating/managing namespaces.

%SYS>d ^DATABASE

 1) Create a database
 2) Edit a database
 3) List databases
 4) Delete a database
 5) Mount a database
 6) Dismount a database
 7) Compact globals in a database
 8) Show free space for a database
 9) Show details for a database
10) Recreate a database
11) Manage database encryption
12) Return unused space for a database
13) Compact free space in a database
14) Defragment globals in a database

Jeffrey Drumm · Aug 3, 2018 go to post

It's possible that a proxy is in use for web access. Browsers can generally auto-discover and configure for those, but other web clients can't ... at least most of the time.

Jeffrey Drumm · Aug 2, 2018 go to post

Does it happen if she logs into the management portal as herself from another workstation? Have you tried starting her browser(s) in Safe mode (no add-ins/plug-ins loaded)? Have you cleared the browser's cookies and cache? Disabled anti-virus? Is it possible that she has JavaScript disabled?

Jeffrey Drumm · Jul 10, 2018 go to post

If you're really set on using the ? notation for pattern matching, see the "ObjectScript Pattern Matching" section of the documentation. In the pattern field of the Match function in the expression editor, you would enter the pattern without a leading question mark. For example, you can use the string ".A" to match any number of upper or lowercase characters, or ".AP" to match any number of upper/lowercase and punctuation characters.

Jeffrey Drumm · Jul 10, 2018 go to post

the Matches method uses the ? (question mark) syntax for pattern matching, not regular expressions. I much prefer the latter ...

Jeffrey Drumm · Jul 9, 2018 go to post

If  you expect to be using regular expressions frequently, it might be worth your while to write a classmethod that extends Ens.Rule.FunctionSet and wraps $MATCH or $LOCATE in something that can be called from a business rule (or DTL for that matter).

/// Custom methods for business rules and DTLs
Class User.Rule.FunctionSet Extends Ens.Rule.FunctionSet
{
/// Accepts a string <var>pString</var> and regular expression pattern <var>pPattern</var>
/// as arguments; returns 0 for no match, and a positive integer indicating the match's
/// position if there is a match.
ClassMethod REMatch(pString As %String, pPattern As %String) As %Integer
  {
              Return $LOCATE(pString,pPattern)
  }
}

You could use $MATCH instead of $LOCATE in the method above, but $MATCH() assumes the supplied pattern is begin- and end-anchored. In other words, $LOCATE("this","is") returns the positive integer 3, which for all Cache boolean purposes evaluates as true. $MATCH("this","is") returns 0 (false) since "^is$" does not match "this".

If the class you create extends Ens.Rule.FunctionSet and resides in your production's namespace, it will be selectable from the function dropdown list in both the Business Rule and DTL expression editors.

Jeffrey Drumm · Jul 9, 2018 go to post

Three possibilities:

  1. Caché wasn't installed to run as cacheusr
  2. a second, administrative group was created for performing start/stop operations and users will need to be added to that instead (see @Katherine Reid's comments)
  3. Someone jiggered the permissions for the binaries in <installdir>/bin; those will need to be fixed
Jeffrey Drumm · Jul 1, 2018 go to post

When you say you can't telnet from your machine, do you mean that you don't have a telnet client installed and/or cannot install one?

Are you connecting to the server via a local LAN connection or through a VPN? There may be port-range restrictions for non-local IP addresses in the VPN server's configuration. Even if you're not using a VPN client to connect, there may be a firewall between your location and the server's location that filters traffic based on source network and/or destination port. Finally, there may be similar rules in the Caché host's internal firewall that could impact connections from specific local networks or hosts. This would explain why an Atelier connection works but a Studio connection does not.

It's also possible that your workstation's firewall/anti-virus may be blocking outbound traffic on specific ports or port ranges. If it's so locked down that you can't install a telnet client to test with, I wouldn't be surprised if this was the case.

Jeffrey Drumm · Jun 21, 2018 go to post

What's the use case for this data? What sort of system(s) will it be delivered to? Have you discussed with their vendors how this data might be digested by the downstream applications?

Jeffrey Drumm · Jun 15, 2018 go to post

Great!

One caveat, though (and not exclusive to the method you're using): If you're using the Source property as the ComponentName argument, it  will contain "Ens.MonitorService" for events such as Queue Wait Alerts.

I inherited a rule where Source was used heavily for alert routing decisions, and worked around it by creating a rule that assigns the Ens.AlertRequest property SourceConfigName to Source early in the rule.

Jeffrey Drumm · Jun 14, 2018 go to post

You could write custom methods that query the source config item's properties for those values and call them from your routing rules. However, a more supportable solution would be to implement managed alerts, which will make those properties directly accessible to you in the Ens.Alerting.NotificationRequest object that's created from the Alert Manager business process.

See Configuring Alert Management in the documentation.

Jeffrey Drumm · Jun 14, 2018 go to post

If your'e sure a result set of no more than 1 row will be returned, just call the %Next() method of the Snapshot object. That'll position the cursor on the first (and, hopefully only) row.

Jeffrey Drumm · Jun 4, 2018 go to post

Hi Sean,

The hive you referenced is already there in the registry; I'm assuming it was created during the installation of the Caché client tools. It's in both HKEY_CURRENT_USER\Software\InterSystems\Cache Studio\Settings\Editor and HKEY_USER\(user key value)\Software\InterSystems\Cache Studio\Settings\Editor. The Hover key wasn't present, so I added it as a REG_DWORD value of 0.

The behavior is different, but it doesn't solve the OP's problem ... the "First Record" tip still displays, but it no longer changes when you move the cursor to a class or method where it would normally populate with helpful information.

Jeffrey Drumm · Jun 4, 2018 go to post

I have Studio installed under Wine on Ubuntu 18.04 and accessing the Options menu in Studio causes it to crash ...

I was able to reproduce the tooltip issue, though. What I found was that if you hover over a method that actually is defined, the usual tool help for that method will display and you can switch to other windows without the annoying "First Record" artifact. Not a solution, obviously, but perhaps a workaround.

Jeffrey Drumm · Jun 4, 2018 go to post

As Atelier is an Eclipse plug-in, you really need to look at it from that perspective. And given that it's really Eclipse that we're talking about, there are so many useful plug-ins for Eclipse (never mind the multiple distributions it's available supplied as) that it's not an easy answer.

I/O performance trumps CPU speed, though, so you'll get the best results with a SSD. I'd say a minimum of a dual-core CPU manufactured within the last 8 years and 4-8 GB of RAM will work satisfactorily unless you're a demon coder. I run Atelier in the JavaScript-HTML distribution of Eclipse on a dual-core-emulated, Windows 7 64bit VM under VMWare 14 on a 32GB ThinkPad T460p (quad-core, 8 threads, 2.7GHz, 2TB SSD), and am usually running 3-4 VMs at a time. Performance seems fine, but I'm not head-down pounding out ObjectScript all day long ...

I'm currently trying to get Eclipse to install on a ThinkPad T420 running Ubuntu 18.04 Desktop to see what it's like but have yet to succeed in getting it to run. I think 18.04 may not be quite ripe enough yet ;)

Jeffrey Drumm · Jun 3, 2018 go to post

When Caché was installed, a group was defined for users who may stop/start/restart it (most likely cacheusr). You'll need to make the non-root user a member of that group, unless you'd prefer to use sudo as previously mentioned.

$ sudo usermod <username> -G cacheusr -a

If the user is already logged in, he/she may need to run newgrp to select cacheusr as their primary group:

$ newgrp cacheusr

Jeffrey Drumm · Jun 2, 2018 go to post

The setting is overridden on a primary mirror member such that all global updates are frozen on a journal write error anyway, so the setting really doesn't matter unless you're operating  in a non-mirrored configuration. I've yet to run across a healthcare implementation of Ensemble that wasn't mirrored, but I suppose they exist somewhere. For those cases, I would enable Freeze on Error. Better late delivery than data loss.

Jeffrey Drumm · Jun 1, 2018 go to post

Hi Larry,

In a code rule, you'll need to concatenate the path string with the k1 variable, as such:

do source.GetFieldStreamRaw(.stream, "PIDgrpgrp(1).ORCgrp(1).OBXgrp("_k1_").OBX:5.1")

Jeffrey Drumm · May 22, 2018 go to post

Complex workflows that include database interaction and response handling are better suited for a Business Process / BPL, and you have complete access to the request and response objects there. You can conditionally route to as many target operations as you desire as well. Is there a reason you would prefer to do all of this through a routing rule?

Jeffrey Drumm · May 16, 2018 go to post

It's not uncommon for mail administrators to disable group/distribution list delivery from external sources. Are you able to send mail to the distribution list via other methods from external domains?

Jeffrey Drumm · May 3, 2018 go to post

The primary practical difference is that the mirror backup databases are mounted read-only, so any methods you might run on a mirror backup can't make changes to the database(s).

Can you provide any additional detail as to what you're trying to do?

Jeffrey Drumm · May 1, 2018 go to post

I believe the "View Raw Contents" feature was added in relatively recent versions of Ensemble, possibly 2013+. What version is your client running?

Jeffrey Drumm · Apr 12, 2018 go to post

Messages dequeued from another business host will have the IsMutable property set to false. Creating a clone of the message with the %ConstructClone() method or creating a new message object via a DTL will give you something you can update.

Jeffrey Drumm · Apr 6, 2018 go to post

The cursor is hovering over the 2nd sub-component of the first component of the field. 3 is the field, 3.1 is the first component of the field, 3.1.1 is the first sub-component of the first component of the field, and 3.1.2 is the second sub-component of the first component of the field. If the field has repetitions (delimited by a ~), the first repetition would be referenced as 3(1), with its components and sub-components referenced as 3(1).1, 3(1).1.1, 3(1).1.2, etc.

Jeffrey Drumm · Apr 6, 2018 go to post

You may already understand this, but it bears repeating: If your intent is to include a literal ampersand symbol, you should also change the sub-component separator in MSH-2 in keeping with the formal HL7 spec.

Unfortunately, many vendors don't understand (or bother to handle) HL7 escaped characters, and some of them don't even pay attention to the values in MSH-2 ... leaving us forced to generate what is essentially badly-formed HL7.

Jeffrey Drumm · Apr 4, 2018 go to post

If you're unable to purge Message Headers that are beyond the retention period with KeepIntegrity turned off, you may need to clean up your indices.  In a Cache terminal, execute the method below in the namespace where your Ensemble production is defined:

> Do ##class(Ens.MessageHeader).%ValidateIndices("",1)

Depending on the number of message headers, this may take a while to run ... on one system I've worked with it took more than a month.

You may want to also check for orphaned message bodies. You can determine if you have any by issuing the following SQL query from the SQL shell:

> Do $system.SQL.Shell()

>> SELECT COUNT(*) FROM EnsLib_HL7.Message HL7 LEFT JOIN Ens.MessageHeader hdr ON HL7.Id=hdr.MessageBodyId WHERE hdr.MessageBodyId IS NULL

Cleaning up the orphaned message bodies is yet another task, but let's see if you have any first ...

Jeffrey Drumm · Mar 26, 2018 go to post

I know this is sort of making an end-run around the issue, but my needs are such that it works well for me.

I run all of my development environments in virtual machines on my laptop. Spinning up a new (or cloning an existing) VM to support a distinct environment gives me the flexibility you appear to need without jeopardizing other software installations.

Jeffrey Drumm · Feb 27, 2018 go to post

The record mapper creates a record definition that can be used as either a source or a target; create the record layout you require in the mapper, then use the DTL editor to define how the HL7 fields are mapped from the HL7 document type to the record map document.