web stats
Mirth Tools: User defined functions - Mirth Community

Go Back   Mirth Community > Mirth Connect > Support

Reply
 
Thread Tools Display Modes
  #1  
Old 04-17-2012, 10:32 AM
upstart33 upstart33 is offline
Mirth Guru
 
Join Date: Dec 2010
Location: Chicago, IL.
Posts: 459
upstart33 is on a distinguished road
Default Mirth Tools: User defined functions

Hi,

Out of a desire to learn, partial boredom, and a double-dog dare, I decided to create a thread topic to list some things that I find useful when dealing with Mirth, creating Channels, or fine-tuning the database.

First, I'd figure I would start out with some functions that some may find useful when developing channels.

Feel free to use them, tweak them, or add more to this thread of others to gaze upon. I hope to start other threads with other tools/scripts/code examples to assist in making our daily Mirth Connect experience that more enjoyable and less migraine inducing.

These functions can be defined and called from within a single Channel itself, or placed into the Code Template section for use throughout all of your Channels.

1. Determine a Channel's status
Purpose: To determine the current state of a channel.

Sometimes, you need to know the status of a certain channel, from within another channel. To accomplish this, you can use the following to see if the channel is :
-STARTED
-STOPPED
-PAUSED
-NA (Non-available)

Code:
function GetChannelState(channel_id) {

    var channel_status = "NA";

    var channel_count = parseInt(Packages.com.webreach.mirth.server.controllers.ChannelStatusController.getInstance().getChannelStatusList().size());

    for(var i=0;i<channel_count;i++) {
        if (channel_id == Packages.com.webreach.mirth.server.controllers.ChannelStatusController.getInstance().getChannelStatusList().get(i).getChannelId()) {
            channel_status = Packages.com.webreach.mirth.server.controllers.ChannelStatusController.getInstance().getChannelStatusList().get(i).getState();
        }
    }

    return channel_status;

}
If you do not know your channel_id, you can view it next to the channel_name on the 'Channels' section of your Mirth Connect Administrator.
Reply With Quote
  #2  
Old 04-17-2012, 10:39 AM
upstart33 upstart33 is offline
Mirth Guru
 
Join Date: Dec 2010
Location: Chicago, IL.
Posts: 459
upstart33 is on a distinguished road
Default

2. Quick SELECT/UPDATE/INSERT functions
Purpose: If most of your channels are connecting to the same database, you can use these functions to cut down some lines of code and for re-usability

Let's say that all of your channels are connecting to the same MySQL database. You could create a SELECT function as such:

Code:
function CDRSelect(sql) {

    var dbConn = DatabaseConnectionFactory.createDatabaseConnection("com.mysql.jdbc.Driver","jdbc:mysql://localhost:3306/cdrexample","USER","PASSWORD");
    
    var results = dbConn.executeCachedQuery(sql);

    dbConn.close();

    return results;
}
Now, in your Source or in a javascript transformer, you can execute a SELECT query by calling the following:

Code:
var results= CDRSelect("SELECT * FROM results");
....and for an UPDATE query, it would look like the following:

Code:
function CDRUpdate(sql) {

    var dbConn = DatabaseConnectionFactory.createDatabaseConnection("com.mysql.jdbc.Driver","jdbc:mysql://localhost:3306/cdrexample","USER","PASSWORD");
    var results = dbConn.executeUpdate(sql);
    dbConn.close();

    return results;
}
...which can be referenced by :

Code:
var results= CDRUpdate("UPDATE results set name = 'test'");
Reply With Quote
  #3  
Old 04-17-2012, 10:43 AM
upstart33 upstart33 is offline
Mirth Guru
 
Join Date: Dec 2010
Location: Chicago, IL.
Posts: 459
upstart33 is on a distinguished road
Default

3. Misc. Trim functions
Purpose: Sometimes, you need to do some trimming of strings. If you do not feeling like memorizing Regex, you can use something along the lines of the following.

Code:
function trim(in_str) {
    return new String(in_str).replace(/^\s+|\s+$/g,"");
}
Code:
function ltrim(in_str) {
    return new String(in_str).replace(/^\s+/,"");
}
Code:
function rtrim(in_str) {
    return new String(in_str).replace(/\s+$/,"");
}

Now, the function can be called within a transformer or mapper step:
Code:
var fname= trim(msg['patient_first'].toString());
Reply With Quote
  #4  
Old 04-17-2012, 11:07 AM
upstart33 upstart33 is offline
Mirth Guru
 
Join Date: Dec 2010
Location: Chicago, IL.
Posts: 459
upstart33 is on a distinguished road
Default

4. Word-Wrap
Purpose: If for some reason, you need to perform some Work Wrapping, then this function emulates PHP's 'wordwrap'.

-The string to be wrapped.
-The column width (a number, default: 75)
-The character(s) to be inserted at every break. (default: \n)
-The cut: a Boolean value (false by default).

Code:
function wordwrap( str, width, brk, cut ) {
 
  brk = (brk ? brk :\n);
  width = (width ? width : 75);
  cut = (cut ? cut : false);
 
    if (!str) { return str; }
 
    var regex = '.{1,' +width+ '}(\\s|$)' + (cut ? '|.{' +width+ '}|.+$' : '|\\S+?(\\s|$)');
 
    return str.match( RegExp(regex, 'g') ).join( brk );
 
}
The function can be called by:
Code:
wordwrap('The quick brown fox jumped over the lazy dog.', 20, '<br/>\n');
---------
The quick brown fox <br/>
jumped over the lazy <br/>
dog.
Reply With Quote
  #5  
Old 04-17-2012, 11:20 AM
upstart33 upstart33 is offline
Mirth Guru
 
Join Date: Dec 2010
Location: Chicago, IL.
Posts: 459
upstart33 is on a distinguished road
Default

5: Local Timzones
Purpose: Sometimes, your not running Mirth locally and you need the correct timezone.

Code:
function getCurrentLocalTimestamp() {
   var formatter = new Packages.java.text.SimpleDateFormat("yyyyMMddhhmmss"); 
   // your local TZ
   formatter.setTimeZone(Packages.java.util.TimeZone.getTimeZone("EST")); 
   return formatter.format(new Packages.java.util.Date()); 
}
The function can be used to get the local server date/time by the following:
Code:
tmp['MSH']['MSH.7']['MSH.7.1'] = getCurrentLocalTimestamp();
Reply With Quote
  #6  
Old 04-17-2012, 12:02 PM
narupley's Avatar
narupley narupley is online now
Mirth Employee
 
Join Date: Oct 2010
Posts: 7,123
narupley is on a distinguished road
Default

Quote:
UPDATE: I've created a public GitHub repository to track these example channels, code templates, scripts, or whatever else!

https://github.com/nextgenhealthcare/connect-examples

To start with I only added the ones I wrote, because I didn't want to presume and add code from others without their explicit permission. Pull requests welcome!
Haha, I'll play along:

xmlToHL7

Deserializes an E4X XML node into HL7 v2.x. This allows you to pass any E4X node of a message and convert it into HL7 v2.x correctly. Here's the code (I've also attached it as a code template):

Code:
function xmlToHL7(node,fieldSeparator,componentSeparator,repetitionMarker,subcomponentSeparator) {
	// Data validation
	if (!node) return '';
	// This shouldn't really ever happen with E4X anyway, but just in case.
	String.prototype.replaceAmp = function() {return this.replace(/&amp;/g,'&');};
	// If we're just dealing with a simple node, then just return its contents.
	if (node.hasSimpleContent()) return node.toString().replaceAmp();
	// Used for StringUtils
	importPackage(org.apache.commons.lang);
	
	// Defaults to standard HL7 encoding characters
	var fs = fieldSeparator || '|';
	var cs = componentSeparator || '^';
	var rm = repetitionMarker || '~';
	var ss = subcomponentSeparator || '&';
	var cr = '\x0D';

	// What will actually be returned
	var output = '';
	// Get the XML name of the node (in the case of an XMLList of repeating fields, the first one will be returned, since they all have the same name anyway)
	var qname = node[0].name().toString();
	// Use the HL7 dot notation to find what level we're at
	var level = StringUtils.countMatches(qname,'.');

	// If the name is HL7Message, we're at the root node
	if (qname == 'HL7Message')
		// Recursively append serialization for each segment
		for each (segment in node.children())
			output += xmlToHL7(segment,fs,cs,rm,ss);

	// If we're at the segment level
	else if (level == 0) {
		// If the node is an XMLList of multiple segments
		if (node.length() > 1) {
			// Recursively append serialization for each segment
			for each (segment in node)
				output += xmlToHL7(segment,fs,cs,rm,ss);
		}
		else {
			// Add the segment name to the output
			output += qname;
			// Initialize name placeholder
			var prevName = '';
			// Iterate through each field in the segment
			for each (field in node.children()) {
				// Get the QName of the field
				var fieldName = field.name().toString();
				// If we're dealing with the special cases of MSH.1/2, then just add the field contents
				if (fieldName in {'MSH.1':1,'MSH.2':1})
					output += field.toString().replaceAmp();
				// Otherwise add the recursive serialization of the field
				else
					// If we're on a field repetition, then prepend a repetition marker, otherwise prepend a field separator
					output += (prevName==fieldName?rm:fs) + xmlToHL7(field,fs,cs,rm,ss);
				// Update the field name placeholder
				prevName = fieldName;
			}
			// Add a carriage return to the end of the segment
			output += cr;
		}
	}

	// If we're at the field level
	else if (level == 1) {
		// If the node is an XMLList of multiple fields
		if (node.length() > 1) {
			// Recursively append serialization for each field
			for each (field in node)
				output += xmlToHL7(field,fs,cs,rm,ss) + rm;
			// Remove the final repetition marker
			output = StringUtils.chomp(output,rm);
		}
		else {
			// Recursively append serialization for each component
			for each (component in node.children())
				// Append a component separator to the end
				output += xmlToHL7(component,fs,cs,rm,ss) + cs;
			// Remove the last component separator
			output = StringUtils.chomp(output,cs);
		}
	}

	// If we're at the component level
	else if (level == 2) {
		// Recursively append serialization for each subcomponent
		for each (subcomponent in node.children())
			// Append a subcomponent separator to the end
			output += xmlToHL7(subcomponent,fs,cs,rm,ss) + ss;
		// Remove the last subcomponent separator
		output = StringUtils.chomp(output,ss);
	}

	// If we're at the subcomponent level
	else
		// Just add the contents of the node
		output = node.toString().replaceAmp();

	// Return the final output
	return output;
}
Examples

Deserialize the entire message:
Code:
logger.info(xmlToHL7(msg));
Deserialize just the PID segment:
Code:
logger.info(xmlToHL7(msg.PID));
Deserialize just the PID.3 segment (even if there are repetitions):
Code:
logger.info(xmlToHL7(msg.PID['PID.3']));
Attached Files
File Type: xml xmlToHL7.xml (4.6 KB, 464 views)

Last edited by narupley; 06-08-2018 at 10:34 AM.
Reply With Quote
  #7  
Old 04-19-2012, 04:47 AM
narupley's Avatar
narupley narupley is online now
Mirth Employee
 
Join Date: Oct 2010
Posts: 7,123
narupley is on a distinguished road
Default

Quote:
UPDATE: I've created a public GitHub repository to track these example channels, code templates, scripts, or whatever else!

https://github.com/nextgenhealthcare/connect-examples

To start with I only added the ones I wrote, because I didn't want to presume and add code from others without their explicit permission. Pull requests welcome!
Fix the node order of an HL7 v2.x E4X XML object

When you add fields/components/subcomponents out of order in a message, it isn't serialized correctly by Mirth. For example, if you have the following code:

Code:
var nte = <NTE/>;

nte['NTE.1']['NTE.1.1'] = '1';
nte['NTE.3']['NTE.3.1'] = 'comment';
nte['NTE.2']['NTE.2.1'] = 'TX';

msg.appendChild(nte);
then your NTE segment will come out looking like:

Code:
NTE|1||comment|TX
Issue 625 is scheduled to be fixed in 3.0, but in the meantime, here's another way to fix it:

fixHL7NodeOrder takes in a single HL7 v2.x node (it can be the root HL7Message, or a single segment/field/component/etc.), and returns the same node, with all children sorted in ascending order as per the HL7 dot notation. So the following node:

Code:
<NTE>
	<NTE.1>
		<NTE.1.1>1</NTE.1.1>
	</NTE.1>
	<NTE.3>
		<NTE.3.1>comment</NTE.3.1>
	</NTE.3>
	<NTE.2>
		<NTE.2.1>TX</NTE.2.1>
	</NTE.2>
</NTE>
would be changed to:

Code:
<NTE>
	<NTE.1>
		<NTE.1.1>1</NTE.1.1>
	</NTE.1>
	<NTE.2>
		<NTE.2.1>TX</NTE.2.1>
	</NTE.2>
	<NTE.3>
		<NTE.3.1>comment</NTE.3.1>
	</NTE.3>
</NTE>
Here's the code, or you can just import the attached code template. Cheers!

Code:
/*
	Author: Nick Rupley
	Date Modified: 4/18/2012

	fixHL7NodeOrder: Returns a new E4X node where the order of all siblings and descendants have been fixed as per the Mirth HL7 dot notation convention.

	Arguments
	---------
		Required
		--------
		node: The node to be fixed. 
*/

function fixHL7NodeOrder(node) {
	// Create output node
	var newNode = new XML();
	// In case the node is an XMLList of multiple siblings, loop through each sibling
	for each (sibling in node) {
		// Create new sibling node
		var newSibling = new XML('<'+sibling.name().toString()+'/>');
		// Iterate through each child node
		for each (child in sibling.children())
			// If the child has its own children, then recursively fix the node order of the child
			if (child.hasComplexContent())
				newSibling.appendChild(fixHL7NodeOrder(child));
			// If the child doesn't have its own children, then just add the child to the new sibling node
			else
				newSibling.appendChild(child);
		// After recursively fixing all of the child nodes, now we'll fix the current node
		newNode += sortHL7Node(newSibling);
	}
	// Return the fixed node
	return newNode;
}

// Helper function for fixHL7NodeOrder
function sortHL7Node(node) {
	// If the node has no children, then there's nothing to sort
	if (node.hasSimpleContent())
		return node;
	// Create new output node
	var newNode = new XML('<'+node.name().toString()+'/>');
	// Iterate through each child in the node
	for each (child in node.children()) {
		// If the child has a QName, then we can sort on it
		if (child.name()) {
			// Get the current "index" of the child. Id est, if the QName is PID.3.1, then the index is 1
			curChildIndex = parseInt(child.name().toString().substring(child.name().toString().lastIndexOf('.')+1),10);
			// Boolean placeholder
			var inserted = false;
			// Iterate through each child currently in the NEW node
			for (var i = 0; i <= newNode.children().length()-1; i++) {
				// Get the index of the child of the new node
				loopChildIndex = parseInt(newNode.child(i).name().toString().substring(newNode.child(i).name().toString().lastIndexOf('.')+1),10);
				// If the child we want to insert has a lower index then the current child of the new node, then we're going to insert the child 
				// right before the current newNode child
				if (curChildIndex < loopChildIndex) {
					// Insert the child
					newNode.insertChildBefore(newNode.children()[i],child);
					// Set our flag, indicating that an insertion was made
					inserted = true;
					// No need to continue iteration
					break;
				}
			}
			// If no insertion was made, then the index of the child we want to insert is greater than or equal to all of the
			// indices of the children that have already been inserted in newNode. So, we'll just append the child to the end.
			if (!inserted)
				newNode.appendChild(child);
		}
	}
	// Return the sorted HL7 node
	return newNode;
}
Attached Files
File Type: xml fixHL7NodeOrder.xml (3.4 KB, 209 views)

Last edited by narupley; 06-08-2018 at 10:34 AM.
Reply With Quote
  #8  
Old 04-19-2012, 06:50 AM
narupley's Avatar
narupley narupley is online now
Mirth Employee
 
Join Date: Oct 2010
Posts: 7,123
narupley is on a distinguished road
Default

Quote:
UPDATE: I've created a public GitHub repository to track these example channels, code templates, scripts, or whatever else!

https://github.com/nextgenhealthcare/connect-examples

To start with I only added the ones I wrote, because I didn't want to presume and add code from others without their explicit permission. Pull requests welcome!
UPDATE 2-13-13: Made a change so that segName can be a regular expression

Okay, this one might be helpful to some people....

getSegmentsAfter: Returns an array of segments with the specified name that come after a given segment in the message.

Say you have multiple OBR groups in your message. Sometimes you want to do something with only the OBXs that come after that particular OBR, and not necessarily all of the OBXs in the entire message. The same goes for NTEs after an OBX, etc. Assuming that you're not using the strict HAPI parser (most of us don't), this might be fairly tricky to do.

The getSegmentsAfter function does it for you. Given the root node (root), the segment you want to start at (startSeg), and the name of the segments you want to get (segName), this function will return an array of those segments.

There are two other optional parameters:
  • consecutiveInd: If this is true, then the segments to be collected are expected to come directly after the starting segment. If any segment is encountered that doesn't have a name of segName, collection is immediately stopped. If this is false, then collection is stopped when another segment of the same name as startSeg is encountered. For example, say you have the following message:
    Code:
    MSH...
    PID...
    OBR...
    OBX...
    OBX...
    NTE...
    OBX...
    OBR...
    OBX...
    If startSeg is the first OBR, segName is "OBX", and consecutiveInd is true, then getSegmentsAfter will return the first two OBXs in the message, but not the third one. If consecutiveInd is false, then it will return the first three OBXs, but not the fourth one.

  • stopSegNames: This is an array of segment names that you want to act as an "emergency brake" to stop collection. If one of these segments is encountered, then iteration is stopped. This is useful when, for example, you have a message like this:
    Code:
    MSH...
    PID...
    OBR...
    OBX...
    NTE...
    OBX...
    SPM...
    OBX...
    In HL7Land, the OBR segment contains two groups, the observation group (consisting of the first two OBXs) and the specimen group (consisting of the SPM and the third OBX). In this case you don't want to get consecutive OBXs because there may be NTEs/ZDSs in between, but on the other hand you don't want to include the OBX that is part of the specimen group. So if "SPM" is included in stopSegNames, then all will be good.

Examples
  • Get all OBXs after the first OBR segment:
    Code:
    getSegmentsAfter(msg,msg.OBR[0],'OBX')
  • Get all consecutive NTEs after the first OBX segment:
    Code:
    getSegmentsAfter(msg,msg.OBX[0],'NTE',true)
  • Get all OBXs after the first OBR segment, but don't include any OBXs in the SPM or ZBP groups:
    Code:
    getSegmentsAfter(msg,msg.OBR[0],'OBX',false,['SPM','ZBP'])
  • Add a new NTE segment to the first OBR group (at the order level rather than the observation level):
    Code:
    var newNTE = <NTE/>;
    newNTE['NTE.3']['NTE.3.1'] = 'whatever';
    var nteGroup = getSegmentsAfter(msg,msg.OBR[0],'NTE',true);
    if (nteGroup.length > 0)
         msg.children()[nteGroup[nteGroup.length-1].childIndex()] += newNTE;
    else
         msg.OBR[0] += newNTE;
  • Reset all of the set IDs of the OBXs after every OBR in the message:
    Code:
    for each (obr in msg.OBR) {
         var obxGroup = getSegmentsAfter(msg,obr,'OBX',false,['SPM','ZBP']);
         for (var i = 0; i <= obxGroup.length-1; i++)
              msg.children()[obxGroup[i].childIndex()]['OBX.1']['OBX.1.1'] = (i+1);
    }
  • Get all Z-segments after each OBR segment:
    Code:
    for each (obr in msg.OBR) {
    	for each (zseg in getSegmentsAfter(msg,obr,/Z[A-Z\d]{2}/)) {
    		// Do something
    	}
    }

The code:

Code:
/*
	Author: Nick Rupley
	Date Modified: 2/13/2013
	getSegmentsAfter: Returns an array of segments with the specified name that come after a given segment in the message.

	Arguments
	---------
		Required
		--------
			root:			The root HL7Message node of the message, or the parent of the segment node.
			startSeg:		The segment AFTER which to start collecting segments.
			segName:		The name (String or RegExp) of the segments you want to collect.

		Optional
		--------
			consecutiveInd:	If true, indicates that the segments are expected to come directly after startSeg. 
					If false, segments are collected until another segment with the same name as startSeg is encountered.
					Defaults to false.
			stopSegNames:	An array of segment names that, when encountered, stop the collection of segments.
*/

function getSegmentsAfter(root, startSeg, segName, consecutiveInd, stopSegNames) {
	function test(str) {
		return segName instanceof RegExp ? segName.test(str) : segName === str;
	}

	// The index to start collection is the next one up from the starting segment
	var index = startSeg.childIndex()+1;
	// The return array
	var out = [];
	// Boolean placeholder to stop iteration
	var done = false;
	// Object that will contain all of the stopSegNames strings, bound to a truthy value (1)
	var stopNames = {};
	// Indicates whether we have any stop segments
	var stopNamesInd = false;
	// If stopSegNames is defined
	if (stopSegNames !== undefined && stopSegNames !== null) {
		// Set our indicator to true
		stopNamesInd = true;
		// Add each string in the array to our object
		for each (name in stopSegNames)
			stopNames[name] = 1;
	}

	// Iterate through each child in the root, starting at the segment after startSeg, and
	// ending at the final segment, or when the done flag is set to true.
	while (index < root.children().length() && !done) {
		// If a stop segment is encountered, stop iteration
		if (stopNamesInd && root.children()[index].name().toString() in stopNames)
			done = true;
		// If a segment with the same name as startSeg is encountered, stop iteration
		else if (root.children()[index].name().toString() == startSeg.name().toString() && !consecutiveInd)
			done = true;
		// If we're only collecting consecutive segments and we encounter a segment with a name other than segName, stop iteration
		else if (!test(root.children()[index].name().toString()) && consecutiveInd)
			done = true;
		// If all previous tests passed, and the current segment has a name of segName, then add it to our array
		else if (test(root.children()[index].name().toString()))
			out.push(root.children()[index]);
		// Increment our index counter
		index++;
	}

	// Return the output array
	return out;
}
Attached Files
File Type: xml getSegmentsAfter.xml (3.0 KB, 418 views)
File Type: xml getSegmentsAfter (new 2-13-13).xml (3.1 KB, 786 views)

Last edited by narupley; 06-08-2018 at 10:35 AM.
Reply With Quote
  #9  
Old 05-09-2012, 08:39 AM
narupley's Avatar
narupley narupley is online now
Mirth Employee
 
Join Date: Oct 2010
Posts: 7,123
narupley is on a distinguished road
Default

NOTE: This code template is probably not necessary for 3.0 because we now have the ChannelUtil utility class, which has methods to deploy/undeploy/start/stop/etc. channels and connectors. However you can still use this to deploy channels on a different instance of Mirth Connect.

deployChannels: Deploys channels using an array of channel IDs and an optional client info object.

Rather self-explanatory; you just pass it an array or comma-separated string of channel IDs, and it will initiate a Client and deploy the specified channels. Client connection settings are hard-coded as defaults, but they can be overridden via the optional clientInfo argument.

The function returns an object containing a status String element, a message String element, and an overloaded toString method. The status will be "SUCCESS" if the client was able to successfully login, and at least one of the channel IDs refers to an enabled channel. Otherwise, the status is "FAILURE".

Here's the code (also attached as a code template):

Code:
/*
	Author: Nick Rupley
	Date Modified: 5/9/2012

	deployChannels
	--------------
		Deploys channels using an array of channel IDs and an optional client info object.

	Arguments
	---------
		Required
		--------
		channelIds: An array of channel IDs, or a string containing a comma-separated list of channel IDs.
		
		Optional
		--------
		clientInfo: An object containing zero or more of the following elements:
			URL: The Mirth Connect Administrator URL to connect to.
			user: Username to connect with.
			pass: Password to connect with.
			version: Version of Mirth Connect to bind to.
			timeout: HTTPS Connection timeout in milliseconds.

	Return Value
	------------
		Returns an object containing a status String element, a message String element, 
		and an overloaded toString method. The status will be "SUCCESS" if the client
		was able to successfully login, and at least one of the channel IDs refers to
		an enabled channel. Otherwise, the status is "FAILURE".
*/

function deployChannels(channelIds,clientInfo) {
	var crlf = '\x0D\x0A', tab = '     ';
	var status = {status:'FAILURE', message:''};
	status.toString = function() {return this.status + ':' + crlf + this.message;};

	try {
		if (!(channelIds instanceof Array)) {
			channelIds = channelIds.replace(/\s/g,'');
			if (channelIds.length > 0)
				channelIds = channelIds.split(',');
			else
				channelIds = [];
		}
		if (channelIds.length <= 0)
			throw('');
	}
	catch(e) {
		status.message = 'Invalid Channel ID List.';
		return status;
	}

	var info = {
		URL: 'https://localhost:8443',
		user: 'admin',
		pass: 'admin',
		version: '2.2.1.5861',
		timeout: 10000
	};
	if (clientInfo) {
		info.URL = clientInfo.URL || info.URL;
		info.user = clientInfo.user || info.user;
		info.pass = clientInfo.pass || info.pass;
		info.version = clientInfo.version || info.version;
		if ((clientInfo.timeout || clientInfo.timeout === 0) && clientInfo.timeout >= 0)	
			info.timeout = clientInfo.timeout;
	}

	try {
		var client = new com.mirth.connect.client.core.Client(info.URL,info.timeout);
		var loginStatus = client.login(info.user,info.pass,info.version);
		status.message += 'Login status: ' + loginStatus.getStatus() + crlf;

		if (!loginStatus.getStatus().toString().startsWith('FAIL')) {
			var list = new java.util.ArrayList();
			var channels = {}, failures = [];
			var successMessage = 'Channels successfully deployed:' + crlf;
			var failureMessage = 'Disabled channels not deployed:' + crlf;

			for each (channel in client.getChannel(null).toArray())
				channels[channel.getId()] = channel.isEnabled();
			for each (channelId in channelIds)
				if (channels[channelId]) {
					list.add(channelId);
					successMessage += tab + channelId + crlf;
				}
				else {
					failures.push(channelId);
					failureMessage += tab + channelId + crlf;
				}

			client.deployChannels(list);
			status.status = list.size() > 0 ? 'SUCCESS' : 'FAILURE';
			status.message += (list.size() > 0 ? successMessage : '') + (failures.length > 0 ? failureMessage : '');
		}
		else
			status.message += loginStatus.getMessage() + crlf;

		try {client.logout();} catch (e) {}
	}
	catch(e) {
		status.status = 'FAILURE';
		status.message += e.toString() + crlf;
	}

	return status;
}
And an example of its use (a channel that accepts a CSV string of channelIds as Delimited Text and outputs the result of deployChannels to the server log):

Code:
logger.info(deployChannels(messageObject.getRawData().split(',')).toString());
Attached Files
File Type: xml deployChannels.xml (3.8 KB, 151 views)

Last edited by narupley; 10-17-2013 at 07:54 AM.
Reply With Quote
  #10  
Old 05-16-2012, 03:20 AM
StefanScholte StefanScholte is offline
 
Join Date: May 2009
Location: Netherlands, Harderwijk
Posts: 321
StefanScholte is on a distinguished road
Default

I believe this will also be useful to others.

Date(Time) is always a pain in the **** especially with javascript.
So we ended up developing a javascript object that does the translation.
note the date is still string based note a javascript Date object.

You can set any date(time) you want and get any other format back.

Code:
/*
	Author(s): Stefan Scholte /Barry van der Veen
	Isala Klinieken Zwolle The Netherlands

	InternalDateTimeObject
	--------------
		Sets or gets Date(time) in numerous formats.

*/

function InternalDateTimeObject()
{
	this.innerDate = '';

	this.GetHL7UniversalDateTimeWithMilliseconds = function() 
	{
		return this.innerDate;
	}

	this.GetHL7UniversalDateTime = function() 
	{
		return this.GetDateFromCustomTemplate("yyyyMMddHHmmss");
	}

	this.GetHL7UniversalDate = function() 
	{
		return this.GetDateFromCustomTemplate("yyyyMMdd");
	}

	this.GetDBDateTimeEN = function() 
	{
		return this.GetDateFromCustomTemplate("yyyy-MM-dd HH:mm:ss");
	}

	this.GetDBDateEN = function() 
	{
		return this.GetDateFromCustomTemplate("yyyy-MM-dd");
	}

	this.GetDBDateTimeNL = function() 
	{
		return this.GetDateFromCustomTemplate("dd-MM-yyyy HH:mm:ss");
	}
	this.GetDBDateNL = function() 
	{
		return this.GetDateFromCustomTemplate("dd-MM-yyyy");
	}

	this.GetTime = function()
	{
		return this.GetDateFromCustomTemplate("HH:mm:ss");
	}

	this.GetTimeWithMilliseconds = function()
	{
		return this.GetDateFromCustomTemplate("HH:mm:ss.SSS");
	}
	this.GetWeek = function()
	{
		return this.GetDateFromCustomTemplate("ww");
	}

	this.SetCurrentDate = function()
	{
		this.innerDate = DateUtil.getCurrentDate('yyyyMMddHHmmssSSS');
	}

	this.SetFromDBDateNL = function(strDate)
	{
		this.innerDate = this.SetDateFromCustomTemplate("dd-MM-yyyy",strDate);
	}

	this.SetFromDBDateEN = function(strDate)
	{
		this.innerDate = this.SetDateFromCustomTemplate("yyyy-MM-dd",strDate);
	}

	this.SetFromDBDateTimeNL = function(strDate)
	{
		this.innerDate = this.SetDateFromCustomTemplate("dd-MM-yyyy HH:mm:ss",strDate);
	}

	this.SetFromDBDateTimeEN = function(strDate)
	{
		this.innerDate = this.SetDateFromCustomTemplate("yyyy-MM-dd HH:mm:ss",strDate);
	}


	this.SetFromHL7UniversalDate = function(strDate)
	{
		this.innerDate = this.SetDateFromCustomTemplate("yyyyMMdd",strDate);
	}

	this.SetFromHL7UniversalDateTime = function(strDate)
	{
		this.innerDate = this.SetDateFromCustomTemplate("yyyyMMddHHmmss",strDate);
	}


	this.GetDateFromCustomTemplate = function (pattern) 
	{
		if (this.innerDate == '')
			return this.innerDate;
		else
			return DateUtil.convertDate ("yyyyMMddHHmmssSSS", pattern, this.innerDate);
	}

	this.SetDateFromCustomTemplate = function (pattern, strDate) 
	{
		if(!strDate || strDate == '')
			return '';
		else
			return DateUtil.convertDate (pattern,"yyyyMMddHHmmssSSS", strDate);
	}
}

//Formatting options
// yyyy year (four-digit)
// M, MM month, month with leading 0
// d, dd day, day with leading 0
// HH hour, 24-hour-format
// hh hour, 12-hour-format
// mm minutes
// ss seconds
// SSS milliseconds
// ww week in year
usage:

Code:
//Make a new InternalDateTimeObject instance.
var date = new InternalDateTimeObject();

//You can set the currentdate in the object
date.SetCurrentDate();
//or set a specific date(time)
date.SetFromDBDateTimeEN("2012-04-30 12:58:57");

//And if you have special formatting you can use this option

date.SetDateFromCustomTemplate ("yyyy/dd/MM/", "2012/03/04") ;

//And this is how you can get the date(times) back.

var englishDateTime = date.GetDBDateTimeEN(); 
var HL7DateTime = date.GetHL7UniversalDateTimeWithMilliseconds();; 


//Here are all the getters
date.GetHL7UniversalDateTimeWithMilliseconds();; 
date.GetHL7UniversalDateTime(); 
date.GetHL7UniversalDate(); 
date.GetDBDateTimeEN(); 
date.GetDBDateEN(); 
date.GetDBDateTimeNL(); 
date.GetDBDateNL(); 
date.GetTime();
date.GetTimeWithMilliseconds();
date.GetWeek();




//And here are all the setters
date.SetCurrentDate();
date.SetFromDBDateNL("30-04-2012");
date.SetFromDBDateEN("2012-04-30");
date.SetFromDBDateTimeNL("30-04-2012 12:58:57");
date.SetFromDBDateTimeEN("2012-04-30 12:58:57");
date.SetFromHL7UniversalDate("20120430");
date.SetFromHL7UniversalDateTime(20120430125857)
date.GetDateFromCustomTemplate ("yyyy/dd/MM/"); 
date.SetDateFromCustomTemplate ("yyyy/dd/MM/", "2012/03/04") ;

Last edited by StefanScholte; 05-16-2012 at 03:34 AM.
Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -8. The time now is 07:22 PM.


Powered by vBulletin® Version 3.8.7
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Mirth Corporation