#51
|
|||
|
|||
![]()
I made a library because I needed to get a formatted datetime string for x number of days prior to now to use in a File Reader.
I put the following line in my channel deploy script to place the object in my globalChannelMap, but I suppose that it could also go in the global deploy script and globalMap, since each channel really doesn't need its own instance of it. Code:
// Get object from code template that can be used to generate filenames with dates in the past. $gc('mdu', MyDateUtil.getJavaObject()); Code:
prefix_${mdu.formatCurrentDateTimeByOffset('yyyyMMdd', 'days', -4)} |
#52
|
|||
|
|||
![]()
Here's my small contribution. I had to work on this some time ago and I though it was worth to share.
Starting with Mirth 3.5 new DB Reader "Aggregate Results" option, this scripts allows you to debatch/aggregate records according to one column value. To use it - go to Source tab, enable Process Batch, enable "Aggregate Results" and set appropriate ORDER BY clause to your query - go to Summary tab, open Set Data Types window, set Split Batch By to Javascript, paste script in corresponding field and set target column name (in lower case) As DB Reader generates pretty printed XML, we are able to build results reading one line after the other. This might change in a future release. EDIT : Actually, while reading it for the first time in weeks, I just figured out there is a much more efficient way to handle this (first version of script is left for info) : Code:
var columnName = "column name in lower case" //<== SET TARGET COLUMN NAME HERE var line = ''; // holds single lines read from buffered reader var result = ''; //string representation of one <result/> element var results = <results/> ; // will hold one batch message var currentAggregation = ''; // anything remaining from last call? var lastResult = $gc('lastReadResult'); // last record read (empty if we start reading) ; WARNING, it's actually a java String, not a js string if(lastResult != null && (''+lastResult).length>0) { // a result was read previously ==> it's part of current "batch" var xmlResult = new XML(lastResult) ; results.appendChild(xmlResult); currentAggregation = xmlResult[columnName].toString(); globalChannelMap.remove('lastReadResult'); } // start/continue reading lines while ((line = reader.readLine()) != null) { // ignore first and last <results> elements if (line != "<results>" && line != "</results>") { line = line.trim(); result += line; // end of a record? if (line == '</result>') { var xmlResult = new XML(result); // get result as XML // same or new batch if (currentAggregation != xmlResult[columnName].toString()) { if (results == '') { // tricky here, an empty <results/> means that we're in the very 1st iteration : we just have to set currentAggregation for next iterations currentAggregation = xmlResult[columnName].toString(); } else { // store new result for next batch $gc('lastReadResult', result); // return this batch return results.toString(); } } // same batch : add result results.appendChild(xmlResult); // reinit for next record result = ''; } } } // one last batch to return? return results.toString(); // will return "" if there's nothing remaining
__________________
Tom Last edited by aTom; 03-19-2018 at 01:39 AM. |
#53
|
|||
|
|||
![]()
If not already known, then there is a Mirth feature called configuration Map available from Settings->ConfigurationMap, where you can store your sensitive Credentials information like DB Credentials, API Credentials and values that are stored can be pulled by just doing configurationMap.get('key'), just like with channel Map.
However, you cannot update details to the configMap from channels or code templates, in a way that configurationMap.put('key') is not possible. It is a read only static Map. Configuration Map Resolver This function returns a credentials object thereby fetching values from the configurationMap. All that is necessary is to settle for a "pattern" while storing information in configurationMap. Let's say that you have stored DB credentials to an EMR database with customerID as ABCD, so I would name the keys as. ABCD-DB_URL ABCD-DB_UserName ABCD-DB_Password Now, I will call the resolver function like configMapResolver('ABCD','DB'); and this will return a credentials object with the information. Code:
function configMapResolver(customerID,type) { sPattern=customerID+'-'+type+'_'; oCredentials=new Object(); oCredentials.Type=type; oCredentials.URL=configurationMap.get(sPattern+'URL'); oCredentials.UserName=configurationMap.get(sPattern+'UserName'); oCredentials.Password=configurationMap.get(sPattern+'Password'); return oCredentials; } You can add more flags like version or environment to it. We use this method for all purpose, DB as well as API credentials (differentiated by the type variable)
__________________
HL7v2.7 Certified Control Specialist! Last edited by siddharth; 03-19-2018 at 06:52 AM. Reason: fix |
#54
|
|||
|
|||
![]()
We had a specific use case where we needed to get the original HL7 "pipe-delimited" representation of selected fields from incoming HL7v2 text messages and use them elsewhere in the channel output. This function allowed us to transform the HL7 message to an E4X message object, pick the specific fields we needed, and convert the XML fragments back to how they appeared in the original HL7 pipe-delimited message.
Function will handle fields with repeating values as well as empty components/sub-components. The function: Code:
/** * Function to convert an E4X XML fragment representing an HL7 field into its original HL7 text representation * * @param XMLList nodeList XML representing the field to translate. * @param array joinStrArray Array containing your HL7 delimiters for repeating fields, components, and subcomponents * @param int joinStrIdx Index representing the current delimiter in joinStrArray to use (should be 0 on first call) * @param int startComponentId Used for recursion; leave null for first call. (Represents the sub-field element the function is starting from.) * * @return string */ function xmlToPipes(nodeList, joinStrArray, joinStrIdx, startComponentId) { var elementList = []; var componentIndex = null; if (startComponentId !== undefined) { componentIndex = parseInt(startComponentId); } for each (node in nodeList) { var nodeChildren = node.elements(); var nodeNameParts = node.name().toString().split('.'); var nodeComponentIndex = parseInt(nodeNameParts.pop()); if (componentIndex === null) { componentIndex = nodeComponentIndex; } var componentIndexDiff = nodeComponentIndex - componentIndex; if (componentIndexDiff > 0) { for (var i = 0; i < componentIndexDiff; i++) { elementList.push(''); componentIndex++; } } if (nodeChildren.length() > 0) { elementList.push(xmlToPipes(nodeChildren, joinStrArray, joinStrIdx+1, 1)); } else { elementList.push(node.toString()); } componentIndex++; } return elementList.join(joinStrArray[joinStrIdx]); } Code:
// array should contain HL7 delimiters you use for (in order) repeating fields, components, and subcomponents var joinStrStarterArray = ["~", "^", "&"]; var msh4 = xmlToPipes(msg['MSH']['MSH.4'], joinStrStarterArray, 0); var pid3 = xmlToPipes(msg['ORU_R01.PATIENT_RESULT']['ORU_R01.PATIENT']['PID']['PID.3'], joinStrStarterArray, 0); |
#55
|
|||
|
|||
![]()
Sometimes you need to alter the globalChannelMap of a running channel but do not want to stop it.
Code:
function $gcById(id, key, value) { var maps = com.mirth.connect.server.util.GlobalChannelVariableStoreFactory.getInstance(); var map; if (maps.globalChannelVariableMap.containsKey(id)) { map = maps.get(id); } else { throw "globalChannelMap not found for channel: " + id; } if (arguments.length == 2) { return map.get(key); } else { return map.put(key, value); } } Code:
$gcById('388f7dfc-4a1a-45a6-b89b-91faacd67044', 'test', 'added from another channel'); logger.info($gcById('febe3d1e-97d6-47eb-bfe0-ca6bf895c967', 'importantMap').toString()); |
#56
|
||||
|
||||
![]() Quote:
extractTextFromPDF: Extracts and returns all text from a PDF. Uses the built-in iText library, version 2.1.7. Parameters:
Examples:
The code: Code:
/** Extracts and returns all text from a PDF. Uses the built-in iText library, version 2.1.7. @param {byte[]} pdfBytes - The raw byte array for the PDF. @return {String} The extracted text. */ function extractTextFromPDF(pdfBytes) { var text = new java.lang.StringBuilder(); var reader = new com.lowagie.text.pdf.PdfReader(pdfBytes); try { var extractor = new com.lowagie.text.pdf.parser.PdfTextExtractor(reader); var pages = reader.getNumberOfPages(); for (var i = 1; i <= pages; i++) { text.append(extractor.getTextFromPage(i)); if (i < pages) { text.append('\n\n'); } } } finally { reader.close(); } return text.toString(); }
__________________
Step 1: JAVA CACHE...DID YOU CLEAR ...wait, ding dong the witch is dead? Nicholas Rupley Work: 949-237-6069 Always include what Mirth Connect version you're working with. Also include (if applicable) the code you're using and full stacktraces for errors (use CODE tags). Posting your entire channel is helpful as well; make sure to scrub any PHI/passwords first. ![]()
Last edited by narupley; 06-08-2018 at 11:37 AM. |
#57
|
||||
|
||||
![]()
FYI, 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!
__________________
Step 1: JAVA CACHE...DID YOU CLEAR ...wait, ding dong the witch is dead? Nicholas Rupley Work: 949-237-6069 Always include what Mirth Connect version you're working with. Also include (if applicable) the code you're using and full stacktraces for errors (use CODE tags). Posting your entire channel is helpful as well; make sure to scrub any PHI/passwords first. ![]()
|
![]() |
Thread Tools | |
Display Modes | |
|
|