Skip to content

Commit 7ef63f8

Browse files
authored
Merge pull request nextgenhealthcare#13 from tonygermano/router
Add Route With Sources code template
2 parents 2ca6bec + 04a92ca commit 7ef63f8

File tree

7 files changed

+359
-0
lines changed

7 files changed

+359
-0
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
This Source Code Form is subject to the terms of the Mozilla Public
2+
License, v. 2.0. If a copy of the MPL was not distributed with this
3+
file, You can obtain one at http://mozilla.org/MPL/2.0/.
4+
5+
Files in this subfolder are Copyright Tony Germano 2023, 2024.
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# Route with Sources
2+
3+
Mirth provides two ways to send messages from one channel to another. The simple way is by using a
4+
Channel Writer destination. This lets choose your destination channel, set optional "Message
5+
Metadata," which will appear in the sourceMap of the new message, and create a template for the
6+
message.
7+
8+
The second method is by using the `VMRouter` class from the User API. Mirth automatically inserts
9+
an instance of this class into the top level javascript scope named `router`. You can send metadata
10+
with your messages using this method as well, but it is slightly more complicated as it requires
11+
constructing a `RawMessage` to pass to the route command.
12+
13+
Additionally, when you use a Channel Writer, it automatically inserts metadata into the sourceMap
14+
representing the current channel and message, as well as any prior channels and messages that may
15+
have participated in the message chain. This functionality does not exist when using the `router`
16+
object to send messages.
17+
18+
This library aims to make sending messages from javascript as easy as using a Channel Writer, while
19+
also incorporating the same channel and message tracking capabilities.
20+
21+
This is accomplished through three related functions. See the source of each function for full
22+
usage.
23+
24+
- **createRawMessage:** This creates an instance of `RawMessage` as specified in the Mirth User
25+
API. Additionally, it mimics the behavior of a Channel Writer destination and appends metadata
26+
to the sourceMap of the `RawMessage` by incorporating the `channelId` and `messageId` from the
27+
current javascript context, if present.
28+
- **routeMessage** Wrapper for `router.routeMessage`, which calls `createRawMessage` from this
29+
library before sending the message. There are optional parameters to pass a sourceMap as the seed
30+
for the one created by `createRawMessage` and for the `destinationSet` to be used by
31+
`createRawMessage`.
32+
- **routeMessageByChannelId** This is the same as the `routeMessage` function from this library
33+
except it wraps `router.routeMessageByChannelId`.
34+
35+
### Getting the Code Templates
36+
The functions are provided in two different ways.
37+
38+
1. A Code Template Library export for mirth versions 3.4.0+.
39+
2. Individual javascript files. These are intended to be copied into three different Code Templates
40+
that belong to the same Code Template Library. You may choose to include only one of the
41+
routeMessage functions, but they both depend on createRawMessage. You may also copy all three
42+
functions into a single code template, and they will work, but this will break the jsdoc parsing
43+
that mirth uses for its code completion.
44+
45+
### Examples
46+
Use as a drop-in replacement for `router.routeMessage` sending a string message, while adding
47+
information about the current channel id and message id to the downstream sourceMap.
48+
49+
```javascript
50+
routeMessage('ADT Processor', connectorMessage.getRawData())
51+
```
52+
53+
Send a binary message. When using a byte[] for your message content, the downstream channel will
54+
receive it as a base64 encoded string.
55+
56+
```javascript
57+
routeMessageByChannelId(downstreamChannelId, javaByteArrayMessage)
58+
```
59+
60+
Send a message with additional custom metadata. Source channel id and message id are always
61+
included.
62+
63+
```javascript
64+
routeMessage('File Sender', messageContent, {targetFileName: 'abc.txt', targetPath: '/files/text'})
65+
```
66+
67+
Only allow message to run for destinations with specified metadata ids. No additonal custom
68+
metadata. Source channel id and message id are always included.
69+
70+
```javascript
71+
routeMessageByChannelId(downstreamChannelId, messageContent, null, [2,3])
72+
```
Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
<codeTemplateLibrary version="3.4.0">
2+
<id>ca9c7efd-2329-4248-bb9a-0271554baeaf</id>
3+
<name>Route With Sources</name>
4+
<revision>2</revision>
5+
<lastModified>
6+
<time>1718998568183</time>
7+
<timezone>America/New_York</timezone>
8+
</lastModified>
9+
<description>Replacement methods for router.routeMessage* functions with added functionality to automatically insert the current channel
10+
and message ids into the source chain in the sourceMap of the downstream channel in the same way that a Channel Writer would
11+
add that information.
12+
</description>
13+
<includeNewChannels>true</includeNewChannels>
14+
<enabledChannelIds/>
15+
<disabledChannelIds/>
16+
<codeTemplates>
17+
<codeTemplate version="3.4.0">
18+
<id>c487e335-9148-4d12-9c0f-c8e5bf10010b</id>
19+
<name>createRawMessage(message, sourceMap, destinationSet)</name>
20+
<revision>2</revision>
21+
<lastModified>
22+
<time>1719010706913</time>
23+
<timezone>America/New_York</timezone>
24+
</lastModified>
25+
<type>FUNCTION</type>
26+
<contextSet>
27+
<delegate>
28+
<contextType>SOURCE_RECEIVER</contextType>
29+
<contextType>CHANNEL_POSTPROCESSOR</contextType>
30+
<contextType>GLOBAL_DEPLOY</contextType>
31+
<contextType>GLOBAL_UNDEPLOY</contextType>
32+
<contextType>GLOBAL_PREPROCESSOR</contextType>
33+
<contextType>CHANNEL_BATCH</contextType>
34+
<contextType>CHANNEL_UNDEPLOY</contextType>
35+
<contextType>CHANNEL_DEPLOY</contextType>
36+
<contextType>DESTINATION_RESPONSE_TRANSFORMER</contextType>
37+
<contextType>DESTINATION_DISPATCHER</contextType>
38+
<contextType>CHANNEL_ATTACHMENT</contextType>
39+
<contextType>GLOBAL_POSTPROCESSOR</contextType>
40+
<contextType>CHANNEL_PREPROCESSOR</contextType>
41+
<contextType>SOURCE_FILTER_TRANSFORMER</contextType>
42+
<contextType>DESTINATION_FILTER_TRANSFORMER</contextType>
43+
</delegate>
44+
</contextSet>
45+
<code>/**
46+
Create a RawMessage with the specified content, sourceMap, and destinationSet. Information about the
47+
chain of source channel Ids and source message Ids will be included in the sourceMap of the new
48+
RawMessage automatically in a similar manner as if a Channel Writer was being used.
49+
50+
If this is called from a context where there is no messageId, a value of -1 will be used.
51+
52+
If this is called from a context where there is no channelId, a value of &quot;NONE&quot; will be used.
53+
54+
@copyright 2023,2024 Tony Germano
55+
@license MPL-2.0
56+
57+
@param {string|byte[]} message - The content of the message to be sent, textual or binary.
58+
@param {Object|java.util.Map} sourceMap - A map containing entries to include in the sourceMap of
59+
the RawMessage (optional).
60+
@param {Array&lt;number&gt;|java.util.Collection&lt;Number&gt;} destinationSet - A collection of integers
61+
(metadata IDs) representing which destinations to dispatch the message to. Null may be passed to
62+
indicate all destinations. If unspecified, all destinations is the default (optional).
63+
@return {RawMessage} - A RawMessage object containing the message, source, and destination
64+
information.
65+
*/
66+
function createRawMessage(message, sourceMap, destinationSet) {
67+
if (typeof destinationSet === &apos;undefined&apos;) destinationSet = null
68+
if (sourceMap == null) sourceMap = java.util.Collections.emptyMap()
69+
70+
const sourceChannelIds = $(&apos;sourceChannelIds&apos;) ? new java.util.ArrayList($(&apos;sourceChannelIds&apos;))
71+
: $(&apos;sourceChannelId&apos;) ? new java.util.ArrayList([$(&apos;sourceChannelId&apos;)])
72+
: new java.util.ArrayList()
73+
const sourceMessageIds = $(&apos;sourceMessageIds&apos;) ? new java.util.ArrayList($(&apos;sourceMessageIds&apos;))
74+
: $(&apos;sourceMessageId&apos;) ? new java.util.ArrayList([$(&apos;sourceMessageId&apos;)])
75+
: new java.util.ArrayList()
76+
77+
const newSourceMap = new java.util.HashMap(sourceMap),
78+
_channelId = typeof channelId !== &apos;undefined&apos; ? channelId : &quot;NONE&quot;,
79+
messageId = new java.lang.Long(typeof connectorMessage !== &apos;undefined&apos; ? connectorMessage.messageId : -1)
80+
81+
sourceChannelIds.add(_channelId)
82+
sourceMessageIds.add(messageId)
83+
84+
newSourceMap.putAll({
85+
sourceChannelIds: sourceChannelIds,
86+
sourceChannelId: _channelId,
87+
sourceMessageIds: sourceMessageIds,
88+
sourceMessageId: messageId
89+
})
90+
91+
return new RawMessage(message, destinationSet, newSourceMap)
92+
}</code>
93+
</codeTemplate>
94+
<codeTemplate version="3.4.0">
95+
<id>f9472423-7df4-4ba9-a002-9029ec99e4dc</id>
96+
<name>routeMessage(channelName, message, sourceMap, destinationSet)</name>
97+
<revision>2</revision>
98+
<lastModified>
99+
<time>1719010706787</time>
100+
<timezone>America/New_York</timezone>
101+
</lastModified>
102+
<type>FUNCTION</type>
103+
<contextSet>
104+
<delegate>
105+
<contextType>SOURCE_RECEIVER</contextType>
106+
<contextType>CHANNEL_POSTPROCESSOR</contextType>
107+
<contextType>GLOBAL_DEPLOY</contextType>
108+
<contextType>GLOBAL_UNDEPLOY</contextType>
109+
<contextType>GLOBAL_PREPROCESSOR</contextType>
110+
<contextType>CHANNEL_BATCH</contextType>
111+
<contextType>CHANNEL_UNDEPLOY</contextType>
112+
<contextType>CHANNEL_DEPLOY</contextType>
113+
<contextType>DESTINATION_RESPONSE_TRANSFORMER</contextType>
114+
<contextType>DESTINATION_DISPATCHER</contextType>
115+
<contextType>CHANNEL_ATTACHMENT</contextType>
116+
<contextType>GLOBAL_POSTPROCESSOR</contextType>
117+
<contextType>CHANNEL_PREPROCESSOR</contextType>
118+
<contextType>SOURCE_FILTER_TRANSFORMER</contextType>
119+
<contextType>DESTINATION_FILTER_TRANSFORMER</contextType>
120+
</delegate>
121+
</contextSet>
122+
<code>/**
123+
Route a message to the specified channelName. Information about the chain of source channel Ids and
124+
source message Ids will be included in the sourceMap of the downstream message automatically in a
125+
similar manner as if a Channel Writer was being used.
126+
127+
@copyright 2023,2024 Tony Germano
128+
@license MPL-2.0
129+
130+
@param {string} channelName - The name of the channel to which to route the message.
131+
@param {string|byte[]} message - The content of the message to be sent, textual or binary.
132+
@param {Object|java.util.Map} sourceMap - A map containing entries to include in the sourceMap of
133+
the sent message (optional).
134+
@param {Array&lt;number&gt;|java.util.Collection&lt;Number&gt;} destinationSet - A collection of integers
135+
(metadata IDs) representing which destinations to dispatch the message to. Null may be passed to
136+
indicate all destinations. If unspecified, all destinations is the default (optional).
137+
@return {Response} - The Response object returned by the channel.
138+
*/
139+
function routeMessage(channelName, message, sourceMap, destinationSet) {
140+
return router.routeMessage(channelName, createRawMessage(message, sourceMap, destinationSet))
141+
}</code>
142+
</codeTemplate>
143+
<codeTemplate version="3.4.0">
144+
<id>09025c2d-2909-49cd-9382-94e81fb65f4d</id>
145+
<name>routeMessageByChannelId(channelId, message, sourceMap, destinationSet)</name>
146+
<revision>2</revision>
147+
<lastModified>
148+
<time>1719010707014</time>
149+
<timezone>America/New_York</timezone>
150+
</lastModified>
151+
<type>FUNCTION</type>
152+
<contextSet>
153+
<delegate>
154+
<contextType>SOURCE_RECEIVER</contextType>
155+
<contextType>CHANNEL_POSTPROCESSOR</contextType>
156+
<contextType>GLOBAL_DEPLOY</contextType>
157+
<contextType>GLOBAL_UNDEPLOY</contextType>
158+
<contextType>GLOBAL_PREPROCESSOR</contextType>
159+
<contextType>CHANNEL_BATCH</contextType>
160+
<contextType>CHANNEL_UNDEPLOY</contextType>
161+
<contextType>CHANNEL_DEPLOY</contextType>
162+
<contextType>DESTINATION_RESPONSE_TRANSFORMER</contextType>
163+
<contextType>DESTINATION_DISPATCHER</contextType>
164+
<contextType>CHANNEL_ATTACHMENT</contextType>
165+
<contextType>GLOBAL_POSTPROCESSOR</contextType>
166+
<contextType>CHANNEL_PREPROCESSOR</contextType>
167+
<contextType>SOURCE_FILTER_TRANSFORMER</contextType>
168+
<contextType>DESTINATION_FILTER_TRANSFORMER</contextType>
169+
</delegate>
170+
</contextSet>
171+
<code>/**
172+
Route a message to the specified channelId. Information about the chain of source channel Ids and
173+
source message Ids will be included in the sourceMap of the downstream message automatically in a
174+
similar manner as if a Channel Writer was being used.
175+
176+
@copyright 2023,2024 Tony Germano
177+
@license MPL-2.0
178+
179+
@param {string} channelId - The unique identifier of the channel to which to route the message.
180+
@param {string|byte[]} message - The content of the message to be sent, textual or binary.
181+
@param {Object|java.util.Map} sourceMap - A map containing entries to include in the sourceMap of
182+
the sent message (optional).
183+
@param {Array&lt;number&gt;|java.util.Collection&lt;Number&gt;} destinationSet - A collection of integers
184+
(metadata IDs) representing which destinations to dispatch the message to. Null may be passed to
185+
indicate all destinations. If unspecified, all destinations is the default (optional).
186+
@return {Response} - The Response object returned by the channel.
187+
*/
188+
function routeMessageByChannelId(channelId, message, sourceMap, destinationSet) {
189+
return router.routeMessageByChannelId(channelId, createRawMessage(message, sourceMap, destinationSet))
190+
}</code>
191+
</codeTemplate>
192+
</codeTemplates>
193+
</codeTemplateLibrary>
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/**
2+
Create a RawMessage with the specified content, sourceMap, and destinationSet. Information about the
3+
chain of source channel Ids and source message Ids will be included in the sourceMap of the new
4+
RawMessage automatically in a similar manner as if a Channel Writer was being used.
5+
6+
If this is called from a context where there is no messageId, a value of -1 will be used.
7+
8+
If this is called from a context where there is no channelId, a value of "NONE" will be used.
9+
10+
@copyright 2023,2024 Tony Germano
11+
@license MPL-2.0
12+
13+
@param {string|byte[]} message - The content of the message to be sent, textual or binary.
14+
@param {Object|java.util.Map} sourceMap - A map containing entries to include in the sourceMap of
15+
the RawMessage (optional).
16+
@param {Array<number>|java.util.Collection<Number>} destinationSet - A collection of integers
17+
(metadata IDs) representing which destinations to dispatch the message to. Null may be passed to
18+
indicate all destinations. If unspecified, all destinations is the default (optional).
19+
@return {RawMessage} - A RawMessage object containing the message, source, and destination
20+
information.
21+
*/
22+
function createRawMessage(message, sourceMap, destinationSet) {
23+
if (typeof destinationSet === 'undefined') destinationSet = null
24+
if (sourceMap == null) sourceMap = java.util.Collections.emptyMap()
25+
26+
const sourceChannelIds = $('sourceChannelIds') ? new java.util.ArrayList($('sourceChannelIds'))
27+
: $('sourceChannelId') ? new java.util.ArrayList([$('sourceChannelId')])
28+
: new java.util.ArrayList()
29+
const sourceMessageIds = $('sourceMessageIds') ? new java.util.ArrayList($('sourceMessageIds'))
30+
: $('sourceMessageId') ? new java.util.ArrayList([$('sourceMessageId')])
31+
: new java.util.ArrayList()
32+
33+
const newSourceMap = new java.util.HashMap(sourceMap),
34+
_channelId = typeof channelId !== 'undefined' ? channelId : "NONE",
35+
messageId = new java.lang.Long(typeof connectorMessage !== 'undefined' ? connectorMessage.messageId : -1)
36+
37+
sourceChannelIds.add(_channelId)
38+
sourceMessageIds.add(messageId)
39+
40+
newSourceMap.putAll({
41+
sourceChannelIds: sourceChannelIds,
42+
sourceChannelId: _channelId,
43+
sourceMessageIds: sourceMessageIds,
44+
sourceMessageId: messageId
45+
})
46+
47+
return new RawMessage(message, destinationSet, newSourceMap)
48+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/**
2+
Route a message to the specified channelName. Information about the chain of source channel Ids and
3+
source message Ids will be included in the sourceMap of the downstream message automatically in a
4+
similar manner as if a Channel Writer was being used.
5+
6+
@copyright 2023,2024 Tony Germano
7+
@license MPL-2.0
8+
9+
@param {string} channelName - The name of the channel to which to route the message.
10+
@param {string|byte[]} message - The content of the message to be sent, textual or binary.
11+
@param {Object|java.util.Map} sourceMap - A map containing entries to include in the sourceMap of
12+
the sent message (optional).
13+
@param {Array<number>|java.util.Collection<Number>} destinationSet - A collection of integers
14+
(metadata IDs) representing which destinations to dispatch the message to. Null may be passed to
15+
indicate all destinations. If unspecified, all destinations is the default (optional).
16+
@return {Response} - The Response object returned by the channel.
17+
*/
18+
function routeMessage(channelName, message, sourceMap, destinationSet) {
19+
return router.routeMessage(channelName, createRawMessage(message, sourceMap, destinationSet))
20+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/**
2+
Route a message to the specified channelId. Information about the chain of source channel Ids and
3+
source message Ids will be included in the sourceMap of the downstream message automatically in a
4+
similar manner as if a Channel Writer was being used.
5+
6+
@copyright 2023,2024 Tony Germano
7+
@license MPL-2.0
8+
9+
@param {string} channelId - The unique identifier of the channel to which to route the message.
10+
@param {string|byte[]} message - The content of the message to be sent, textual or binary.
11+
@param {Object|java.util.Map} sourceMap - A map containing entries to include in the sourceMap of
12+
the sent message (optional).
13+
@param {Array<number>|java.util.Collection<Number>} destinationSet - A collection of integers
14+
(metadata IDs) representing which destinations to dispatch the message to. Null may be passed to
15+
indicate all destinations. If unspecified, all destinations is the default (optional).
16+
@return {Response} - The Response object returned by the channel.
17+
*/
18+
function routeMessageByChannelId(channelId, message, sourceMap, destinationSet) {
19+
return router.routeMessageByChannelId(channelId, createRawMessage(message, sourceMap, destinationSet))
20+
}

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ This is a repository of example channels, code templates, and other scripts you
2020
- Overwrite Logger Categories
2121
- Rename HL7 Field
2222
- Replace in All Descendant XML Nodes
23+
- Route with Sources
2324
- Run on Startup
2425
- Strip Empty Nodes from XML
2526
- Thread-safe get or create from globalMap

0 commit comments

Comments
 (0)