Shamil NizamovUnofficial Mirth Connect v3.5 Developer’s Guide* * - Preview Version Copyright Page  Copyright © 2013-2017 by Shamil Nizamov      Cover image copyright © 2013 by Shamil Nizamov     All rights reserved. No part of the contents of this book may be reproduced or      transmitted in any form or by any means without the written permission of the author.     Mirth Connect is a trademark of Mirth Corporation. HL7 and Health Level Seven are      registered trademarks of Health Level Seven International. All other marks are property      of their respective owners.  Any rights not expressly granted herein are reserved.  The companies, organizations, products, domain names, email addresses, logos , people,      places, and/or data mentioned herein in examples are fictitious. No association with any      real company, organization, product, domain name, email address, logo, person, place,      or data is intended or should be inferred.     This book expresses the author’s views and opinions. The information contained in this      book is provided without any express, statutory, or implied warranties. The author, Mirth      Corporation, Health Level Seven International, resellers and distributors will NOT be held      liable for any damages caused or alleged to be caused either directly or indirectly by this      book.     This is a preview version of the book.     Introduction   2 Contents PART 1            MIRTH CONNECT BASICS Chapter 1         Getting Started ........................................................................................................ 15                   Installation ............................................................................................................... 15                   Mirth Connect Administrator .................................................................................... 16  Chapter 2         What is a Channel? .................................................................................................. 18                   Connectors............................................................................................................... 19                   Filters ...................................................................................................................... 19                   Transformers............................................................................................................ 20                   Scripts...................................................................................................................... 21  Chapter 3         Creating a Channel ................................................................................................... 23                   Source Connector ..................................................................................................... 24                   TMP, MSG and MESSAGE .......................................................................................... 25                   Destination Connectors............................................................................................. 27                   Testing the Channel .................................................................................................. 31                   Global Map, Global Channel Map, Channel Map ......................................................... 34                   Global Scripts ........................................................................................................... 36                   Code Templates........................................................................................................ 38    PART II           GENERIC ELIGIBILITY SERVICE IMPLEMENTATION  Chapter 4         Generic Eligibility Service Introduction...................................................................... 42                   Eligibility Service Introduction ................................................................................... 42                   Scenario Overview .................................................................................................... 43                   Messages and Interactions Overview ......................................................................... 44                   Eligibility Query Channels Overview ........................................................................... 45    Chapter 5         Query Sender Channel.............................................................................................. 48                   Summary Tab ........................................................................................................... 48                   Source Connector .................................................................................................... 50                   Destinations Connector ............................................................................................ 50                   Channel Implementation Verification......................................................................... 54  3        Introduction Chapter 6    HL7v2 to HL7v3 Transformer Channel ....................................................................... 57              Summary Tab ........................................................................................................... 57              Source Connector .................................................................................................... 58              Destinations Connector ............................................................................................ 60              Code Templates........................................................................................................ 66              Scripts...................................................................................................................... 67              Channel Implementation Verification......................................................................... 68 Chapter 7    Data Logger Channel ................................................................................................ 69              Summary Tab ........................................................................................................... 69              Source Connector .................................................................................................... 70              Destinations Connector ............................................................................................ 71              Code Templates........................................................................................................ 76              Global Scripts ........................................................................................................... 76              Channel Implementation Verification......................................................................... 78 Chapter 8    HL7v3 Verification Channel....................................................................................... 80              Summary Tab ........................................................................................................... 81              Source Connector .................................................................................................... 81              Destinations Connector ............................................................................................ 84              Code Templates........................................................................................................ 90              Global Scripts ........................................................................................................... 91              Scripts...................................................................................................................... 92              Channel Implementation Verification......................................................................... 93 Chapter 9    Response Sender Channel ........................................................................................ 96              Summary Tab ........................................................................................................... 96              Source Connector .................................................................................................... 97              Destinations Connector ............................................................................................ 99              Scripts.................................................................................................................... 102              Channel Implementation Verification....................................................................... 103 Chapter 10   HL7v3 to HL7v2 Transformer Channel .................................................................... 105              Summary Tab ......................................................................................................... 105              Source Connector .................................................................................................. 106              Destinations Connector .......................................................................................... 106                                                                                                                 Introduction           4                  Channel Implementation Verification....................................................................... 109  PART III         ACKNOWLEDGEMENTS IMPLEMENTATION  Chapter 11       Acknowledgements Introduction ............................................................................ 112                  Scenario Overview .................................................................................................. 112                  Acknowledgement Channels Overview .................................................................... 113 Chapter 12       HL7v3 ACK Channel ................................................................................................ 115                  Summary Tab ......................................................................................................... 115                  Source Connector .................................................................................................. 116                  Destinations Connector .......................................................................................... 116                  Scripts.................................................................................................................... 117 Chapter 13       HL7v3 Verification ACK Channel.............................................................................. 119                  Destinations Connector .......................................................................................... 119                  Code Templates...................................................................................................... 122                  Scripts.................................................................................................................... 123                  Source Connector .................................................................................................. 124 Chapter 14       HL7v2 to HL7v3 Transformer ACK Channel ............................................................. 125                  Destinations Connector .......................................................................................... 125                  Code Templates...................................................................................................... 128                  Scripts.................................................................................................................... 129                  Source Connector .................................................................................................. 130                  Channel Implementation Verification ...................................................................... 131 Chapter 15       Query Sender ACK Channel .................................................................................... 132                  Destinations Connector .......................................................................................... 132                  Source Connector .................................................................................................. 134                  Channel Implementation Verification ...................................................................... 136  PART IV          DICOM Chapter 16       DICOM Storage SCU .............................................................................................. 138                  Scenario Overview ................................................................................................. 138                  Summary Tab ........................................................................................................ 140                  Source Connector .................................................................................................. 141                  Destinations Connector .......................................................................................... 142  5       Introduction Chapter 17   DICOM Storage SCP ............................................................................................... 143              Summary Tab ........................................................................................................ 144              Source Connector .................................................................................................. 145              Destinations Connector .......................................................................................... 151              Code Templates ..................................................................................................... 158              Scripts ................................................................................................................... 158              Channels Implementation Verification ..................................................................... 158  PART V       ADVANCING IN MIRTH CONNECT  Chapter 18   Debugging JavaScript in Mirth Connect .................................................................. 161              Built in Logger function .......................................................................................... 161              Rhino JavaScript Debugger in Standalone Mode ....................................................... 162              Rhino JavaScript Debugger in Embedded Mode ........................................................ 163              Eclipse JSDT Debugger in Embedded Mode .............................................................. 168              Console Input ......................................................................................................... 172 Chapter 19   Utilizing JMS (Java Message Service) ...................................................................... 174              Scenario Overview .................................................................................................. 175              Sending Messages .................................................................................................. 176              Sending Objects...................................................................................................... 183              Channels Implementation Verification ..................................................................... 189 Chapter 20   Polling Web Services ............................................................................................. 191              Scenario Overview .................................................................................................. 191              Summary Tab ......................................................................................................... 192              Source Connector .................................................................................................. 192              Destinations Connector .......................................................................................... 193              Channels Implementation Verification ..................................................................... 199 Chapter 21   Building Extensions ............................................................................................... 201              Creating Templates................................................................................................. 203              Signing Extension.................................................................................................... 208              Deploying Extension ............................................................................................... 210              Extension Implementation Verification .................................................................... 211    Introduction           6 Chapter 22            Tuning Mirth Connect ............................................................................................ 213                       Performance Tuning ............................................................................................... 214                       Security Protection ................................................................................................. 219    Book Resources.............................................................................................................................. 223    PART V                APPENDICES                       A: Eligibility Query Request (QUCR_IN200101) Template .......................................... 225                       B: Eligibility Query Results (QUCR_IN210101) Template ............................................ 226                       C: MS Access Log Database Structure ....................................................................... 227                       D: PostgreSQL Eligibility Database Structure ............................................................. 227                       E: XSLT to transform from HL7v3 to HL7v2 ............................................................... 228                       F: JavaScriptTask.java.............................................................................................. 230                       G: Rhino Script Engine script samples ...................................................................... 233                       H: Archives Content ................................................................................................ 239     7         Introduction       Introduction  Introduction       As Mirth Corporation (now is a subsidiary of Quality Systems, Inc.) says on their web-site,       “Mirth Connect is the Swiss Army knife of healthcare integration engines, specifically       designed for HL7 message integration. It provides the necessary tools for developing,       testing, deploying, and monitoring interfaces. And because it’s open source, you get all of       the advantages of a large community of users with commercial quality support.”  In addition, “The 2014 HL7 Interface Technology Survey Results” show that Mirth Connect       is one of the fastest growing healthcare messaging platforms due to its open source       paradigm, and robust functionality for HL7 messaging and X12 documents. Mirth       Connect also speeds up the development of interfaces for data exchange across different       formats and diverse healthcare systems environment.  This book describes version 3.x of Mirth Connect to the point that reader are confident       enough to start building their own healthcare data exchange interfaces and transforming       various versions of HL7 messages.  As you read this book, you will be implementing a fictitious Eligibility Query Service. Each       connection point (channel) is explained in a separate chapter, which in turn provides       step-by-step instructions on how to create and code data transformation rules.  This book is written using Mirth Connect 3.5.0 version of the product. Consequently,       other releases may include new features, or features used in this book may change or       disappear. You may also notice some differences between screen shots provided in the       book and those you see when using Mirth Connect.  Who is this book for?  I wrote this book primarily for application developers and system integrators who have       found the online Mirth Connect documentation lacking and needed a guidebook that       explains things in a more detailed and organized way.  In a book of this size, I cannot cover every feature that Mirth Connect v3.x or previous       versions have; consequently, I assume you already have some familiarity with Mirth       Connect.     Introduction     8       Assumption  This book assumes that you are dealing with applications that use message-oriented       middleware products and expects that you have at least a minimal understanding of       Web service technologies including, but not limited to, XML, XML Schemas, XPath, XSL       Transformation and SOAP/WSDL.  Before you start reading this book, you should have a basic knowledge of JavaScript and       Java; MS Access and PostgreSQL databases from a database administrator perspective;       and are familiarity with operating system environment variables settings.  You should also have basic knowledge of HL7, the standard that is being used to       exchange healthcare data, both version 2 and version 3; and DICOM, the standard for       handling information in medical imaging.  Who should not read this book?  As mentioned earlier, the purpose of this book is to provide the reader with a high -level       overview of the capabilities and features associated with Mirth Connect v3.5. This book is       not intended to be a step-by-step comprehensive guide or substitute of any kind to       original training and certification programs provided by Mirth Corporation (Quality       Systems, Inc.).  This book is also not a tutorial on a specific messaging or middleware technology       implementation. All examples included in this book are for illustrative purposes only. If       you are interested in learning more about a specific technology or product, please refer       to one of the many on-line resources.  This book does not cover any specific installation, configuration, deployment or       monitoring activities for system administrators.  Errata and Book Support  I have made every effort to ensure the accuracy of this book and its companion content.       If you find an error, please report through email - 
[email protected]  Warning and Disclaimer  The purpose of this book is to educate and entertain. Every effort has been made to       make this book as complete and as accurate as possible, but no warranty or fitness is       implied.   9     Introduction      The information is provided on an “as is” basis. The author shall have neither liability nor      responsibility to any person or entity with respect to any loss or damage caused, or      alleged to be caused, directly or indirectly by the information contained in this book or      from the use of software mentioned in this book. The information, methods and      techniques described by the author are based on his own experience. They may not work      for you and no recommendation is made to follow the same course of action. No      representation is made that following the advice in this book will work in your case.  The author is not an employee or representative of Mirth Corporation (Quality Systems,      Inc.) and never has been, and author’s views and opinions are not necessarily those of      Mirth Corporation. This book is not based on trainings or certifications provided by Mirth      Corporation (Quality Systems, Inc.).  This book contains links to third-party websites that are not under the control of the      author, and the author is not responsible for the content of any linked site. If you access      a third-party website mentioned in this book, then you do so at your own risk. The      author provides these links only as a convenience, and the inclusion of the link does not      imply that the author endorses or accepts any responsibility for the content of those      third-party sites.  Furthermore, this book contains information on the subject only up to the published      date.     Acknowledgements  Like most books, this guide has been a long time in the making. I would like to      acknowledge everyone who has assisted in this project. I could not have done this      without you.  Nathan Blakley and Elliot Freedman volunteered to review early versions of a few      chapters. Your feedback helped steer me in the right direction. I’d like to thank Philip      Helger in making an active contribution to the development of the open source      Schematron validator.  My biggest thanks go to Wayne Zafft, who was incredibly gracious with his time and      effort in reviewing the final version of the book.     Introduction     10 Roadmap  This book is divided into five parts:  Part 1 provides an introduction to Mirth Connect and a high-level overview of channels.           Chapter 1, Getting Started            Introduces Mirth Connect at a high level, and demonstrates how to download and            install Mirth Connect Server and Administrator.      Chapter 2, What is a Channel            Provides an overview of the channel architecture implemented in Mirth Connect. It            also covers a channel’s major components such as connectors, filters, transformers            and scripts.      Chapter 3, Creating a Channel            Walks the reader through the creation and configuration of a simple channel. It            covers some of the major points of the Mirth Connect channels implementation            model such as tmp and msg variables, different types of maps and their visibilities. It            also covers Global Scripts, channel scripts and Code Templates.    Part 2 focuses on the implementation of an imaginary but complete eligibility service.      Chapter 4, Generic Eligibility Service Introduction            Introduces the Eligibility Service as defined in the HL7v3 Normative Edition, presents            the implementation plan and walks through the required components.      Chapter 5, Query Sender Channel            Walks the reader through the implementation of the first channel in a chain that            serves as an interface to send HL7v2 Eligibility Query messages.      Chapter 6, HL7v2-HL7v3 Transformer Channel            Explains the implementation of a channel that plays the role of a conduit or broker.            The chapter shows how to establish a MLLP connection to other channels, how to            filter messages based on some criteria and transform messages from one format to            another using different techniques that Mirth Connect provides.    11       Introduction    Chapter 7, Data Logger Channel     Explains the implementation of a channel that uses a file and MS Access database as     destinations.     Chapter 8, HL7v3 Verification Channel     Walks the reader through the implementation of the XML Schema and Schematron     validators using external Java classes.     Chapter 9, Response Sender Channel     Provides insight into implementation of a database-facing channel that retrieves     data, forms the message and passes it along using a SOAP connector.     Chapter 10, HL7v3 to HL7v2 Transformer Channel     Concludes the implementation of the Eligibility service and provides a detailed     explanation on configuring the SOAP connector and XSL Transformation.    Part 3 is dedicated to the implementation of acknowledgements.     Chapter 11, Acknowledgements Introduction     Provides introduction and presents the implementation plan of a message     acknowledgement based on the Eligibility Service implemented in Part 2.     Chapter 12, HL7v3 ACK Channel     Explains how to create another interim channel that receives routed HL7v3 messages     and stores them in a file.     Chapter 13, HL7v3 Verification ACK Channel     Explains how to expand functionalities of the already existing channel to send HL7v3     MCCI acknowledgements.     Chapter 14, HL7v2 to HL7v3 Transformer ACK Channel     Explains how to expand functionalities of the already existing channel to send HL7v2     RSP^E45 acknowledgements back and intercept HL7v3 acknowledgements received     from other channels.     Chapter 15, Query Sender ACK Channel     Explains how to intercept HL7v2 acknowledgements received from one channel and     route them to another channel.     Introduction    12      Part 4 covers topics related to DICOM.      Chapter 16, DICOM SCU           Provides a short introduction and presents the implementation plan of a simplified           DICOM router. Walks the reader through the implementation of the first channel in a           chain that serves as an interface to send DICOM messages.      Chapter 17, DICOM SCP           Provides an in-depth explanation of such important topics as parsing DICOM           messages, extracting objects from a PDF file, creating and deleting template nodes,           encoding PDF file to be submitted by HL7 messages.    Part 5 covers advanced topics.      Chapter 18, Debugging JavaScript in Mirth Connect           Provides an in-depth explanation of such important topics as debugging filters and           transformers JavaScript using built-in and external tools such as Rhino JavaScript           Debugger and Eclipse JSDT Debugger.      Chapter 19, Utilizing JMS (Java Message Service)           Introduces the JMS Sender and Listener connector configurations to pass messages           and objects through a Message Broker such as Apache ActiveMQ. Provides insight           into passing messages, and gives a detailed explanation of serialization /           deserialization techniques to pass Java objects via the Message Broker.      Chapter 20, Polling Web Services           Explains how to extend the functionality of the Web Server Sender connector to           periodically poll data from external service providers.      Chapter 21, Building Extensions           Provides an in-depth explanation of such confused topic as building the Mirth           Connect extension using the example of building a JSON Writer Destination           Connector.      Chapter 22, Tuning Mith Connect           Walks the reader through Mirth Connect Server settings to increase the overall           system’s performance. The chapter also provides a brief overview of available security           enhancement settings.    13       Introduction PART I – MIRTH CONNECT BASICS  Mirth Connect Basics CHAPTER 1   Getting Started  CHAPTER 2   What is a Channel?  CHAPTER 3   Creating a Channel     PART I – MIRTH CONNECT BASICS   14 CHAPTER 1 Getting Started   Getting Started        This chapter outlines the Mirth Connect basic installation procedure. All examples in         this book are based on the Windows version of Mirth Connect v3.5, available to            download at - http://www.mirthcorp.com/community/downloads  Make sure your computer meets minimum system requirements before you start:            Oracle JRE version 1.8 or higher;            1 GB of RAM is recommended;            A web browser.   Installation  There are two possible ways to install Mirth Connect based on what package you have        downloaded or what package is available on the website. In one case, the package is an        archive of all files and classes that you need to run Mirth Connect on your computer. You        simply unzip and copy the package to an appropriate folder, for example to the        C:\Program Files\Mirth Connect\. In the other case, there is a GUI based installer        that you just start and go through the steps in the installation wizard. The installation        process itself is quite straight forward.  In both cases what is installed are Mirth Connect Server, Mirth Connect Server Manager,        Mirth Connect Administrator and Mirth Connect Command Line Interface. During the        installation you have to decide which port will be used by the Mirth Connect Server. By        default it is 8080 for unsecure communication and 8443 for the SSL connection. You can        change it later using the Mirth Connect Server Manager.  To verify the installation:            Launch the Mirth Connect Server either through the Mirth Connect Server Manager             or the Mirth Connect Command Line;            Open the web browser and type localhost:8080 in the address bar;            Click the Access Secure Site button in Web Dashboard Sign In launch page;            Type admin for the user name and repeat admin as the password, click Sign in.  If you see the Dashboard statistics page with, most likely, no channels available, you have        successfully done the installation and ready to continue. If not, refer to Mirth Connect 3.0    15       PART I – MIRTH CONNECT BASICS     User Guide written by “the same Mirth technical experts who developed the software”     available at - http://info.mirth.com/Connect_Documentation_Download.html  Configuration  The Mirth Connect Server Manager can be used as a single point to launch Mirth     Connect Service, configure ports, allocated memories, and database connections.     However, a fully-fledged configuration description is beyond the scope of this book.  Here is only a recommended step is to add a path to the \custom-lib folder to the     operating system’s CLASSPATH environment variable. This is the folder where you put     your Java classes, libraries and other required files.  Versions 1 and 2 of Mirth Connect were using port 1099 for viewing statistics though the     JMX (Java Management Extensions ) and RMI (Remote Method Invocation) interfaces.     This port is no longer used in version 3.x. Hence, if any of your applications or firewall is     utilizing ports 8080 or 8443 you can either change Mirth’s ports using Mirth Connect     Server Manager or manually modify the configuration file located in     \conf\mirth.properties. Don’t forget to restart the Mirth Connect Server or Service for     any changes to make effect.  Mirth Connect Administrator  The Mirth Connect Administrator is a Java application that is not explicitly installed on a     local computer by default in a distributed environment. It is downloaded from the Mirth     Connect Server. The reason for this is to ensure the Mirth Connect Administrator     matches version of the Mirth Connect Server.  To download the Mirth Connect Administrator:        Start Mirth Connect Server if it is not already running as a service;        Open the web browser;        Type localhost:8080 in the address bar;        Click Launch Mirth Connect Administrator in the Mirth Connect Administrator launch         page;        Click Ok to open the webstart.jnlp;        Type admin for the user name and repeat admin as the password in the Mirth         Connect Login pop-up window, then click Login.  If everything is done correctly, each time you login, you will see the Dashboard as the     initial screen. The Dashboard displays two information panels:  PART I – MIRTH CONNECT BASICS   16          Channels status and statistics - the number of messages Received, Filtered,           Queued, Sent, and Errored. The Dashboard Tasks area on the navigation bar on the           left side has menu items essential for developing channels such as Refresh, Send           Messages, and Remove All Messages. Same menu items can be accessed faster by           right clicking on a channel row.          Logs – Server Log, Connection Log and Global Maps. The Server Log is used a lot to           debug channels development. Double-clicking on a Server Log entry brings a pop-up           window where you can view and copy the entire log entry content. The Server Log is           stored by Mirth Connect Server in the database and therefore closing and opening           the Mirth Connect Administrator brings back all entries not previously explicitly           purged. To clear the Server Log click Clear Displayed Log under the Server Log or           Connection Log area.  Logging Level  Channel’s log level can be configured manually by changing \conf\log4j.properties      entries. Available options are: ERROR, WARN, INFO, DEBUG, and TRACE with DEBUG      selected by default. Log levels may be configured separately for filters, transformers,      postprocessors and other scripts that are explained later in this book.     FIGURE 1-1 Mirth Connect Administrator window by default  Familiarize yourself with other navigation items and tabs since this is the main tool used      to develop channels throughout this book.   17       PART I – MIRTH CONNECT BASICS CHAPTER 2 What is a Channel?   What is a Channel?      Theabstract            Channel is an essential part of Mirth Connect and can be seen as one-to-many                  unidirectional pipes to decouple components from each other to transfer          healthcare data between two or more applications. The channel architecture      implemented in Mirth Connect can divide a large message processing task into a      sequence of smaller independent steps. This affords developers the flexibility for      dependency, maintenance and/or performance. Some of the processing tasks can even      be external to Mirth Connect and developed independ ently.     FIGURE 2-1 Mirth Connect abstract channel architecture  In general, each channel consists of inbound and outbound Connectors, Filters and      Transformers. The connector that receives inbound messages from the Sending      Application is called the Source. Similarly, the connector that sends outbound messages      is called the Destination. From the Source connector data is passed through the channel,      where filters and transformers perform operations on the data, for example, routing a      message to one or another Destination connector and transforming the data      representation. Deciding channel’s tasks is when wearing an analyst's hat comes into      play.  Before you create a new channel, you need to elicit the following requirements:         Type of Application the channel reads data from (Source connector type);         Type of Application the channel sends data to (Destination connector type);         Type and format of the inbound message;         Type and format of the outbound message(s);                                                               PART I – MIRTH CONNECT BASICS   18            Mapping table(s) between inbound and outbound messages (Transformation).   Connectors  In terms of Enterprise Integration, the connector is a Message Endpoint that specifies a        particular way or, more accurately, a particular protocol Mirth Connect should us e to        communicate with an external application or another Mirth Connect channel.  Mirth Connect supports sending and receiving messages over a variety of connectors        listed here in no particular order:            TCP/MLLP;            Database (MySQL, PostgreSQL, Oracle, Microsoft SQL Server, ODBC);            File (local file system and network shares);            PDF and RTF documents;            JMS;            HTTP (note that HTTPS is not supported in the free version);            SMTP;            SOAP (over HTTP).  The connector that receives the data is called a Reader, for example the MLLP Reader.        The connector that sends the data is called a Writer, the Database Writer is an example.  Connector types are configured under the Source and Destinations tabs of the channel,        which is explained later in this chapter. As should be obvious, some settings are common        across all connectors while others are unique to a specific connector type.  If you need a connector that is not shipped with the Mirth Connect installation package,        you can develop your own one (such as a custom HTTPS connector). Some templates        and developer’s level documentation for such development are in the chapter dedicated        to Mirth extensions.  Filters  In a real world scenario, when numerous applications and channels are connected, a        channel may receive messages from several sources and these messages may have to be        processed differently, based on the message type or other criteria.  There are two paradigms for solving this problem, a Router and a Filter:     19       PART I – MIRTH CONNECT BASICS        Router connects to multiple outbound channels. The key benefit of the Router is that         the decision criteria for the destination(s) of a message are maintained in a single         location.        Filter, this is what Mirth Connect uses, is built into a message processing mechanism         and is responsible for determining whether the message should be processed or not.         The Filter inspects message properties (segments or elements) without removing the         message from the message queue. If the message cannot be consumed by this         particular pipe, it is returned to the queue unchanged for another pipe to filter or         process.  Filters can be as simple as specific elements comparison against a hard coded value or as     complex as JavaScript scripts and external Java classes. Filters can also be omitted     allowing all messages to pass through. Some routing capabilities have been introduced     starting Mirth Connect v3.1 by using a "destinationSet". If a destination is removed     from the destination set, this destination will not receive the message.  If a single channel needs to process more than one type of messages, you can create any     number of separate pipes – Destinations - and specify none, one or more filters for each     of them.  Transformers  More often than not, messages are sent between legacy systems, custom applications     and third-party solutions, each of which is built around a proprietary data model. Even     systems that claim to support a single standard may place specific requirements on data     format and content. If we could bring all legacy systems to a single format when a new     business requirement is proposed, we would avoid conversion issues. Unfortunately, for     most legacy systems, data format, content or data sequence changes are difficult and     risky, and simply not feasible.  How do we communicate data using different formats then? In Mirth Connect this is     done by a message Transformer that translates one data format into another. As a result,     a destination application expects to receive messages it understands which can be     processed and stored in the application’s internal data format.  Mirth Connect allows message translation to occur at different levels, and to chain     message transformers to achieve a required result.  Supported transformers are:   PART I – MIRTH CONNECT BASICS     20           Message Builder maps segments of the inbound message to segments in the            outbound message.           Iterator works similarly to Message Builder but allows to iterate over multiple            instances of the same segment and map segments of the inbound message to            segments in the outbound message.           Mapper maps segments of the inbound message to internal Mirth Connect variables.            These variables may be used later.           External Script, as the name suggests, employs external JavaScripts to transform or            map the data.           XSLT Step utilizes the XSL transformation.           JavaScript, along with External Script, is where flexibility comes into play. Here any            type of (Rhino) Java Script and Java code can be used.  Scripts  Channels also support unique features called Scripts to enhance the message processing       logic. Scripts apply to a channel itself and all messages that are passing through.  These scripts are:           Deploy script is executed each time Mirth Connect Server starts or a channel is            redeployed. This is the best place to initialize variables or create class objects.           Attachment script deals with a message in a native format and allows extracting a            part of the message to store as an attachment or to irrevocably modify a message.           Preprocessor script also allows handling each message in a native format before            Mirth Connect starts translating it into the internal format, which is XML.           Filter & Transformer scripts are the main places where you handle the inbound and            outbound messages.           Response script, as the name suggests, handles the response sent by a destination.           Postprocessor script is executed after the message has been successfully sent.           Undeploy script is launched each time Mirth Connect Server stops. This is the place            to, for example, release memory that was allocated for the classes used by the            channel.  Scripts are performed in the following order:            1. Global Deploy script;            2. Deploy;            3. Attachment script;            4. Global Preprocessor script;            5. Preprocessor script;  21       PART I – MIRTH CONNECT BASICS    6. Source connector Filters script;    7. Source connector Transformer script or mapping;    8. Destination 1 connector Filters script;    9. Destination 1 connector Transformer script or mapping;    10. Destination N connector Filters script;    11. Destination N connector Transformer script or mapping;    12. Response 1 Transformer script or mapping;    13. Response N transformer script or mapping;    14. Postprocessor script;    15. Global Postprocessor script;    16. Undeploy;    17. Global Undeploy script.  Deploy and Undeploy scripts are performed only once, when a channel is deployed or undeployed, respectively. It is important to note that Global Deploy and Deploy scripts are also executed every time any channel is redeployed. Same with Undeploy and Global Undeploy scripts, they are executed for every channel. All other scripts are performed every time a message is sent through a channel or an acknowledgement is received. Notice that the Global Preprocessor script is executed before the channel’s Preprocessor script is executed. Similarly, after the channel’s Postprocessor script completes, the Global Postprocessor script is run.  If channels operate in series, the Attachment Script of the first channel is the first to perform. The Postprocessor Script of the same channel will be executed last, after all other scripts in all consequent channels. (see Figure 2-2)     FIGURE 2-2 Scripts execution sequence  Next, we will explore each of these steps in detail.  PART I – MIRTH CONNECT BASICS    22                         This is a preview edition of the book.  The full versions of this and other related books are available to                                   download at                   http://mirthconnect.shamilpublishing.com     23   PART I – MIRTH CONNECT BASICS ook Resources   Book Resources        Other titles you may be interested in:  Unofficial Developer's Guide to CCD on Mirth                                           Connect  This book introduces readers to version 3.x of Mirth                                           Connect to the point that they are confident enough                                           to start building their own healthcare data exchange                                           interfaces.  By implementing an imaginary CCD Builder Server,                                           this book covers topics on XSL Transformation,                                           acknowledgements implementation, XML schema and                                           Schematron validation. Each connection point                                           (channels and destinations) is explained in a separate                                           chapter, which in turn provides step-by-step                                           instructions on how to create and code data                                           transformation rules for ADT and ORU messages.  The book is available to download at –                                           http://ccdonmirth.shamilpublishing.com     Unofficial Developer's Guide to FHIR on Mirth                                           Connect  This book describes version 3.x of Mirth Connect to                                           the point that reader are confident enough to start                                           building their own healthcare data exchange                                           interfaces using a new HL7 standard called FHIR or                                           Fast Healthcare Interoperability Resources.  This book may be interesting for those implementing                                           HL7 FHIR based solutions.  The book is available to download at –                                           http://fhironmirth.shamilpublishing.com    PART I – MIRTH CONNECT BASICS   24                                      Unofficial Developer's Guide to HL7v3 Basics  This book introduces readers to HL7 version 3 to the                                      point that they are confident enough to start building                                      their own healthcare data exchange interfaces. The                                      book provides clear and easy to use, step-by-step                                      guidance for learning the standard, with numerous                                      examples covering many topics.  This book may be interesting for those implementing                                      the Clinical Document Architecture (CDA) or HL7                                      Reference Information Model (aka RIM) based                                      solutions.  The book is available to download at –                                      http://hl7basics.shamilpublishing.com     25   PART I – MIRTH CONNECT BASICS     APPENDICES  Appendices A: Eligibility Query Request (QUCR_IN200101) Template     <?xml version="1.0" encoding="UTF-8"?>     <QUCR_IN200101UV01 ITSVersion="XML_1.0" xmlns="urn:hl7-org:v3" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">                 <id root="2.16.840.1.113883.1.3" extension=""/>                 <creationTime value=""/>                 <versionCode controlInformationRoot="2.16.840.1.113883.11.19373" code="V3PR1"/>                 <interactionId root="2.16.840.1.113883.1.6" extension="QUCR_IN200101UV01"/>                 <profileId controlInformationRoot="2.16.840.1.113883.9" controlInformationExtension="Elig Query Request, Gen"/>                 <processingCode code="D"/>                 <processingModeCode code="T"/>                 <acceptAckCode code="NE"/>                 <receiver typeCode="RCV">                             <device classCode="DEV" determinerCode="INSTANCE">                                         <id controlInformationRoot="2.16.840.1.113883.101.1"     controlInformationExtension="Organization"/>                                         <asAgent classCode="AGNT">                                                     <representedOrganization classCode="ORG" determinerCode="INSTANCE">                                                                 <id controlInformationRoot="2.16.840.1.113883.101.1"     controlInformationExtension=""/>                                                     </representedOrganization>                                         </asAgent>                             </device>                 </receiver>                 <sender typeCode="SND">                             <device classCode="DEV" determinerCode="INSTANCE">                                         <id controlInformationRoot="2.16.840.1.113883.101.2"     controlInformationExtension="Organization"/>                                         <asAgent classCode="AGNT">                                                     <representedOrganization classCode="ORG" determinerCode="INSTANCE">                                                                 <id controlInformationRoot="2.16.840.1.113883.101.2"     controlInformationExtension=""/>                                                     </representedOrganization>                                         </asAgent>                             </device>                 </sender>                 <controlActProcess classCode="CACT" moodCode="EVN">                             <code code="QUCR_TE200101UV01" codeSystem="2.16.840.1.113883.11.19427"/>                             <authorOrPerformer typeCode="AUT">                                         <assignedPerson classCode="ASSIGNED">                                                     <id controlInformationRoot="2.16.840.1.113883.101.10.1"     controlInformationExtension=""/>                                                     <representedOrganization classCode="ORG" determinerCode="INSTANCE">                                                                 <id controlInformationRoot="2.16.840.1.113883.101.2"     controlInformationExtension=""/>                                                     </representedOrganization>                                         </assignedPerson>                             </authorOrPerformer>                             <queryByParameter>                                         <statusCode code="new"/>                                         <parameterList>                                                     <id extension=""/>                                                     <carrierRole.id>                                                                 <value nullFlavor="NI"/>                                                     </carrierRole.id>                                                     <coveredPartyAsPatient.Id>                                                                 <value root="2.16.840.1.113883.101.10.2" extension=""/>                                                     </coveredPartyAsPatient.Id>                                                     <coveredPartyAsPatientPerson.BirthTim e>                                                                 <value value=""/>                                                     </coveredPartyAsPatientPerson.BirthTime>                                                     <coveredPartyAsPatientPerson.Name>                                                                 <value>                                                                             <part type="FAM" value=""/>                                                                             <part type="GIV" value=""/>                                                                             <part type="GIV" qualifier="MID" value=""/>                                                                 </value>                                                     </coveredPartyAsPatientPerson.Name>                                                     <policyOrAccount.Id>                                                          <value root="2.16.840.1.113883.101.3" extension="MSP"/>                                               </policyOrAccount.Id>                                               <serviceDate>                                                          <value validTimeLow=""/>                                               </serviceDate>                                     </parameterList>                           </queryByParameter>                </controlActProcess>       </QUCR_IN200101UV01>   B: Eligibility Query Results (QUCR_IN210101) Template       <?xml version="1.0" encoding="UTF-8"?>       <QUCR_IN210101UV01 ITSVersion="XML_1.0" xmlns="urn:hl7-org:v3" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">                   <id root="2.16.840.1.113883.1.3" extension=""/>                   <creationTime value=""/>                   <versionCode controlInformationRoot="2.16.840.1.113883.11.19373" code="V3PR1"/>                   <interactionId root="2.16.840.1.113883.1.6" extension="QUCR_IN210101UV01"/>                   <profileId controlInformationRoot="2.16.840.1.113883.9" controlInformationExtension="Elig Query Results, Gen"/>                   <processingCode code="D"/>                   <processingModeCode code="T"/>                   <acceptAckCode code="NE"/>                   <receiver typeCode="RCV">                               <device classCode="DEV" determinerCode="INSTANCE">                                           <id controlInformationRoot="2.16.840.1.113883.101.2"       controlInformationExtension="Organization"/>                                           <asAgent classCode="AGNT">                                                       <representedOrganization classCode="ORG" determinerCode="INSTANCE">                                                                   <id controlInformationRoot="2.16.840.1.113883.101.2"       controlInformationExtension="EligibilityServiceOrganization"/>                                                       </representedOrganization>                                           </asAgent>                               </device>                   </receiver>                   <sender typeCode="SND">                               <device classCode="DEV" determinerCode="INSTANCE">                                           <id controlInformationRoot="2.16.840.1.113883.101.1"       controlInformationExtension="Organization"/>                                           <asAgent classCode="AGNT">                                                       <representedOrganization classCode="ORG" determinerCode="INSTANCE">                                                                   <id controlInformationRoot="2.16.840.1.113883.101.1"       controlInformationExtension="Organization"/>                                                       </representedOrganization>                                           </asAgent>                               </device>                   </sender>                   <acknowledgement typeCode="AA">                               <targetMessage>                                           <id root="2.16.840.1.113883.1.3" extension=""/>                               </targetMessage>                   </acknowledgement>                   <controlActProcess classCode="CACT" moodCode="EVN">                               <code code="QUCR_TE210101UV01" codeSystem="2.16.840.1.113883.1.18"/>                               <subject typeCode="SUBJ">                                           <policyOrAccount classCode="COV" moodCode="EVN" negationInd="false">                                                       <code code="PUBLICPOL"/>                                                       <author typeCode="AUT">                                                                   <carrierRole classCode="UNDWRT">                                                                               <id root="2.16.840.1.113883.101.1"       extension="
[email protected] "/>                                                                   </carrierRole>                                                       </author>                                           </policyOrAccount>                               </subject>                               <reasonOf typeCode="RSON">                                           <detectedIssueEvent classCode="ALRT" moodCode="EVN">                                                       <code code="" controlInformationRoot="2.16.840.1.113883.11.208"/>                                                       <text value=""/>                                           </detectedIssueEvent>                               </reasonOf>                               <queryAck>                                           <queryResponseCode code="OK" controlInformationRoot="2.16.840.1.113883.11.208"/>                               </queryAck>                               <queryByParameter>                                           <parameterList>                                                       <id nullFlavor="NI"/>                                                       <carrierRole.id>                                                                   <value nullFlavor="NI"/>  27      APPENDICES                                              </carrierRole.id>                                              <coveredPartyAsPatient.Id>                                                          <value root="2.16.840.1.113883.101.10.2" extension=""/>                                              </coveredPartyAsPatient.Id>                                              <coveredPartyAsPatientPerson.BirthTime>                                                          <value value=""/>                                              </coveredPartyAsPatientPerson.BirthTime>                                              <coveredPartyAsPatientPerson.Name>                                                          <value>                                                                     <part type="FAM" value=""/>                                                                     <part type="GIV" value=""/>                                                          </value>                                              </coveredPartyAsPatientPerson.Name>                                              <policyOrAccount.Id>                                                          <value root="2.16.840.1.113883.101.3" extension="MSP"/>                                              </policyOrAccount.Id>                                              <serviceDate>                                                          <value nullFlavor="NI"/>                                              </serviceDate>                                    </parameterList>                          </queryByParameter>               </controlActProcess>      </QUCR_IN210101UV01>   C: MS Access Log Database Structure  Create a table called Messages and add following fields:      Field                 Type                                                    Comment      id                    AutoNumber      CreationDate          Date/Time                                               Format: yyyy-mm-dd hh:nn:ss      UUID                  Text      MsgType               Text      Trigger               Text      Version               Text      Errors                Memo      Source                Memo     D: PostgreSQL Eligibility Database Structure      -- Table: messages      -- DROP TABLE messages;  CREA TE TABLE messages      (        id serial NOT NULL, -- autoincrementing id        mid character varying(40), -- inbound message identifier, /QUCR_IN200101UV01/id/@extension        cdate character varying(20), -- inbound message creation date,      /QUCR_IN200101UV01/creationTime/@value        sender character varying(100), -- inbound message sending organization,      /QUCR_IN200101UV01/sender/device/asAgent/representedOrganization/id/@controlInformationExtension        author character varying(100), -- assigned person identifier        pid integer -- link to patients.id table      )      WITH (        OIDS=FALSE      );      ALTE R TABLE messages        OWNE R TO postgres;      COMME NT ON TAB LE messages        IS 'Contain QUCR_IN200101 (Elig Query Request) message related information. For the test purpose      only.';      COMME NT ON COLUMN messages.id IS ' autoincrementing id';  APPENDICES   28       COMME NT ON COLUMN messages.mid IS 'inbound message identifier,       /QUCR_IN200101UV01/id/@extension';       COMME NT ON COLUMN messages.cdate IS 'inbound message creation date,       /QUCR_IN200101UV01/creationTime/@value';       COMME NT ON COLUMN messages.sender IS 'inbound message sending organization,       /QUCR_IN200101UV01/sender/device/asAgent/representedOrganization/id/@controlInformationExtension';       COMME NT ON COLUMN messages.author IS 'assigned person identifier,       /controlActProcess/authorOrPerformer/assignedPerson/id/@controlInformationExtension';       COMME NT ON COLUMN messages.pid IS 'link to patients.id table';  -- Table: patients       -- DROP TABLE patients;  CREA TE TABLE patients       (         id serial NOT NULL, -- autoincrementing id         fname character varying(100), -- patient first name,                /controlActProcess/queryByParameter/parameterList/coveredPartyAsPatientPerson.Name/value/p       art[1]/@value         lname character varying(100), -- patient last name,       /controlActProcess/queryByParameter/parameterList/coveredPartyAsPatientPer son.Name/value/part[1]/@       value         pid character varying(10), -- patient person identifier,       /controlActProcess/queryByParameter/parameterList/coveredPartyAsPatient.Id/value/@extension         dob character varying(15), -- patient date of birth,       /controlActProcess/queryByParameter/parameterList/coveredPartyAsPatientPerson.BirthTime/value/@val       ue         processed boolean NOT NULL DEFAULT false -- QUCR_IN210101 (Elig Query Results) response sent       flag       )       WITH (         OIDS=FALSE       );       ALTE R TABLE patients         OWNE R TO postgres;       COMME NT ON TAB LE patients         IS 'Patient personal information sent by QUCR_IN200101 (Elig Query Request) message. For the       test purpose only.';       COMME NT ON COLUMN patients.id IS 'autoincrementing id';       COMME NT ON COLUMN patients.fname IS 'patient first name,       /controlActProcess/queryByParameter/parameterList/coveredPartyAsPatientPer son.Name/value/part[1]/@       value';       COMME NT ON COLUMN patients.lname IS 'patient last name,       /controlActProcess/queryByParameter/parameterList/coveredPartyAsPatientPerson.Name/value/part[1]/@       value';       COMME NT ON COLUMN patients.pid IS 'patient person identifier,       /controlActProcess/queryByParameter/parameterList/coveredPartyAsPatient.Id/value/@extension';       COMME NT ON COLUMN patients.dob IS 'patient date of birth,       /controlActProcess/queryByParameter/parameterList/coveredPartyAsPatientPerson.BirthTime/value/@val       ue';       COMME NT ON COLUMN patients.processed IS 'QUCR_IN210101 (Elig Query Results) response sent       flag';     E: XSLT to transform from HL7v3 to HL7v2       <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform ">                    <xsl:output method="xml" encoding="UTF-8" indent="yes"/>                    <xsl:template match="/">                                  <HL7Message>                                                <MSH>                                                            <MSH.1>|</MSH.1>                                                            <MSH.2>^~\&</MSH.2>                                                            <MSH.3>                                                                         <MSH.3.1>ADM</MSH.3.1>                                                            </MSH.3>                                                            <MSH.4>                                                                         <MSH.4.1>Sending Organization</MSH.4.1>   29       APPENDICES                                                    </MSH.4>                                                    <MSH.5>                                                                 <MSH.5.1>ALL</MSH.5.1>                                                    </MSH.5>                                                    <MSH.6>                                                                 <MSH.6.1>Receiving Organization</MSH.6.1>                                                    </MSH.6>                                                    <MSH.7>                                                    <MSH.7.1>                                                                 <xsl:value-of select="substring-before(/QUCR_IN210101UV01/creationTime/@value,'- ')"/>                                                    </MSH.7.1>                                                    </MSH.7>                                                    <MSH.9>                                                                 <MSH.9.1>RSP</MSH.9.1>                                                                 <MSH.9.2>E22</MSH.9.2>                                                    </MSH.9>                                                    <MSH.10>                                                                 <xsl:value-of select="/QUCR_IN210101UV01/id/@extension"/>                                                    </MSH.10>                                                    <MSH.11>                                                                 <MSH.11.1>D</MSH.11.1>                                                    </MSH.11>                                                    <MSH.12>                                                                 <MSH.12.1>2.4</MSH.12.1>                                                    </MSH.12>                                                    <MSH.13/>                                                    <MSH.14/>                                                    <MSH.15>                                                                 <MSH.15.1>AL</MSH.15.1>                                                    </MSH.15>                                                    <MSH.16/>                                       </MSH>                                       <MSA>                                                    <MSA.1>                                                                 <MSA.1.1>AA</MSA.1.1>                                                    </MSA.1>                                                    <MSA.2>                                                                 <MSA.2.1>                                                                        <xsl:value-of select="/QUCR_IN210101UV01/acknowledgement/targetMessage/id/@extension "/>                                                           </MSA.2.1>                                                </MSA.2>                                    </MSA>                                    <QAK>                                                <QAK.1/>                                                <QAK.2>                                                           <QAK.2.1>OK</QAK.2.1>                                                </QAK.2>                                                <QAK.3>                                                           <QAK.3.1>E22</QAK.3.1>                                                           <QAK.3.2/>                                                           <QAK.3.3>CIHI0003</QAK.3.3>                                                </QAK.3>                                    </QAK>                                    <QPD>                                                <QPD.1>                                                           <QPD.1.1>E22</QPD.1.1>                                                           <QPD.1.2/>                                                           <QPD.1.3>CIHI0003</QPD.1.3>                                                </QPD.1>                                                <QPD.2>                                                           <QPD.2.1/>                                                </QPD.2>                                                <QPD.3/>                                    </QPD>                                    <PID>                                                <PID.1/>                                                <PID.2/>                                                <PID.3>                                                           <PID.3.1>                                                                        <xsl:value-of select="/QUCR_IN210101UV01/controlActProcess/queryByParameter/parameterList/coveredPartyAsPatient.Id/value/@extension"/>                                                           </PID.3.1>                                                           <PID.3.2/>                                                           <PID.3.3>ISO</PID.3.3>                                                           <PID.3.4>PHN</PID.3.4>                                                </PID.3>                                                <PID.4/>                                                <PID.5>                                                           <PID.5.1>                                                                        <xsl:for-each select="/QUCR_IN210101UV01/controlActProcess/queryByParameter/parameterList/coveredPartyAsPatientPerson.Name/value/*">                                                                                      <xsl:if test="./@type = 'FAM'">                                                                                                      <xsl:value-of select="./@value"/>                                                                                      </xsl:if>                                                                        </xsl:for-each>                                                           </PID.5.1>                                                           <PID.5.2>                                                                        <xsl:for-each select="/QUCR_IN210101UV01/controlActProcess/queryByParameter/parameterList/coveredPartyAsPatientPerson.Name/value/*">                                                                                      <xsl:if test="./@type = 'GIV'">                                                                                                      <xsl:value-of select="./@value"/>   APPENDICES               30                                                                                              </xsl:if>                                                                                </xsl:for-each>  </PID.5.2>                                                                    <PID.5.3/>                                                                    <PID.5.4/>                                                                    <PID.5.5>L</PID.5.5>                                                        </PID.5>                                                        <PID.6/>                                                        <PID.7>                                                                 <PID.7.1>                                                                              <xsl:value-of       select="/QUCR_IN210101UV01/controlActProcess/queryByParameter/parameterList/coveredPartyAsPatientPerson.BirthTime/value/@value "/>                                                                 </PID.7.1>                                                      </PID.7>                                                      <PID.8>                                                                 <PID.8.1/>                                                      </PID.8>                                              </PID>                                   </HL7Message>                     </xsl:template>       </xsl:stylesheet>     F: JavaScriptTask.java       Rhino JS Debugger Embedded       /*        * Copyright (c) Mirth Corporation. All rights reserved.        *        * http://www.mirthcorp.com        *        * The software in this package is published under the terms of the MPL license a copy of which has        * been included with this distribution in the LICENSE.txt file.        */  package com.mirth.connect.server.util.javascript;  import java.util.concurrent.Callable;  import   org.apache.commons.lang3.StringUtils;       import   org.apache.log4j.Logger;       import   org.mozilla.javascript.Context;       import   org.mozilla.javascript.Script;       import   org.mozilla.javascript.Scriptable;  import com.mirth.connect.donkey.util.ThreadUtils;  /* (SN) Debugger declaration starts */       import org.mozilla.javascript.tools.debugger.Main;       /* (SN) Debugger declaration ends */  public abstract class JavaScriptTask<T> implements Callable<T> {  private   Logger logger = Logger.getLogger(JavaScriptTask.class);            private   MirthContextFactory contextFactory;            private   Context context;            private   boolean contextCreated = false;  /* (SN) Debugger declaration starts */            private static Main rhinoDebugger = null;            /* (SN) Debugger declaration ends */  public JavaScriptTask(MirthContextFactory contextFactory) {                this.contextFactory = contextFactory;            }  public MirthContextFactory getContextFactory() {                return contextFactory;            }  public void setContextFactory(MirthContextFactory contextFactory) {                this.contextFactory = contextFactory;            }  protected Context getContext() {   31       APPENDICES           return context;     }  public Object executeScript(Script compiledScript, Scriptable scope) throws InterruptedException {         try {             // if the executor is halting this task, we don't want to initialize the context yet             synchronized (this) {                 ThreadUtils.checkInterruptedStatus();                 context = Context.getCurrentContext();                 Thread.currentThread().setContextClassLoader(contextFactory.getApplicationClassLoader());                 logger.debug(StringUtils.defaultString(StringUtils.trimToNull(getClass().getSimpleName()), getClass().getName()) + " using context factory: " + contextFactory.hashCode());  /*                    * This should never be called but exists in case executeScript is called from a                    * different thread than the one that entered the context.                    */                   if (context == null) {                       contextCreated = true;                       context = JavaScriptScopeUtil.getContext(contextFactory);                   }  if (context instanceof MirthContext) {                       ((MirthContext) context).setRunning(true);                   }              }  /* (SN) Debugger entry starts */ if (rhinoDebugger == null) {          final String title = StringUtils.defaultString(StringUtils.trimToNull(getClass().getSimpleName()), getClass().getName()) + " using context factory: " + contextFactory.hashCode();          rhinoDebugger = Main.mainEmbedded(contextFactory, scope, title);          rhinoDebugger.setExitAction(null); } rhinoDebugger.attachTo(contextFactory); rhinoDebugger.setScope(scope); rhinoDebugger.pack(); rhinoDebugger.setVisible(true); /* (SN) Debugger entry ends */  return compiledScript.exec(context, scope);           } finally {               if (contextCreated) {                   Context.exit();                   contextCreated = false;               }           }     } }     Eclipse JSDT Debugger Embedded /*  * Copyright (c) Mirth Corporation. All rights reserved.  *  * http://www.mirthcorp.com  *  * The software in this package is published under the terms of the MPL license a copy of which has  * been included with this distribution in the LICENSE.txt file.  */  package com.mirth.connect.server.util.javascript;  import java.util.concurrent.Callable;  import   org.apache.commons.lang3.StringUtils; import   org.apache.log4j.Logger; import   org.mozilla.javascript.Context; import   org.mozilla.javascript.Script; import   org.mozilla.javascript.Scriptable;  import com.mirth.connect.donkey.util.ThreadUtils;    APPENDICES        32      /* (SN) Debugger declaration starts */      import org.eclipse.wst.jsdt.debug.rhino.debugger.RhinoDebugger;      /* (SN) Debugger declaration ends */   public abstract class JavaScriptTask<T> implements Callable<T> {  private   Logger logger = Logger.getLogger(JavaScriptTask.class);          private   MirthContextFactory contextFactory;          private   Context context;          private   boolean contextCreated = false;  /* (SN) Debugger declaration starts */          private static RhinoDebugger rhinoDebugger = null;          /* (SN) Debugger declaration ends */   public JavaScriptTask(MirthContextFactory contextFactory) {              this.contextFactory = contextFactory;          }  public MirthContextFactory getContextFactory() {              return contextFactory;          }  public void setContextFactory(MirthContextFactory contextFactory) {              this.contextFactory = contextFactory;          }  protected Context getContext() {              return context;          }  public Object executeScript(Script compiledScript, Scriptable scope) throws InterruptedException {              try {                  // if the executor is halting this task, we don't want to initialize the context yet                  synchronized (this) {                      ThreadUtils.checkInterruptedStatus();                      context = Context.getCurrentContext();                      Thread.currentThread().setContextClassLoader(contextFactory.getApplicationClassLoader());                      logger.debug(StringUtils.defaultString(StringUtils.trimToNull(getClass().getSimpleName()),      getClass().getName()) + " using context factory: " + contextFactory.hashCode());  /*                         * This should never be called but exists in case executeScript is called from a                         * different thread than the one that entered the context.                         */                        if (context == null) {                            contextCreated = true;                            context = JavaScriptScopeUtil.getContext(contextFactory);                        }  if (context instanceof MirthContext) {                            ((MirthContext) context).setRunning(true);                        }                    }  /* (SN) Debugger entry starts */      if ( null == context.getDebugger() ) {               rhinoDebugger = new RhinoDebugger("transport=socket,suspend=y,address=9009");          try { rhinoDebugger.start(); } catch(Exception ex){System.out.println(ex.getMessage());};          rhinoDebugger.contextCreated(context);      }      contextFactory.addListener(rhinoDebugger);      /* (SN) Debugger entry ends */  return compiledScript.exec(context, scope);              } finally {                  if (contextCreated) {      /* (SN) Debugger stop */      try { rhinoDebugger.stop(); } catch(Exception ex){System.out.println(ex.getMessage());};      /* (SN) Debugger stop */                      Context.exit();                      contextCreated = false;                  }              }          }      }   33      APPENDICES G: Rhino Script Engine script samples  Source and Destination connector scripts as they executed by the Mirth Connect Server      using Rhino Script Engine. Code is manually tweaked and commented for better      readability.  Channel Source Connector script  function $co(key, value) {          if (arguments.length == 1) {              return connectorMap.get(key);          } else {              return connectorMap.put(key, value);          }      }  function $c(key, value) {          if (arguments.length == 1) {              return channelMap.get(key);          } else {              return channelMap.put(key, value);          }      }  function $s(key, value) {          if (arguments.length == 1) {              return sourceMap.get(key);          } else {              return sourceMap.put(key, value);          }      }  function $gc(key, value) {          if (arguments.length == 1) {              return globalChannelMap.get(key);          } else {              return globalChannelMap.put(key, value);          }      }  function $g(key, value) {          if (arguments.length == 1) {              return globalMap.get(key);          } else {              return globalMap.put(key, value);          }      }  function $cfg(key, value) {          if (arguments.length == 1) {              return configurationMap.get(key);          } else {              return configurationMap.put(key, value);          }      }  function $r(key, value) {          if (arguments.length == 1) {              return responseMap.get(key);          } else {              return responseMap.put(key, value);          }      }  function $(string) {          try {              if (responseMap.containsKey(string)) {                  return $r(string);              }          } catch (e) {}          try {   APPENDICES   34              if (connectorMap.containsKey(string)) {                  return $co(string);              }          } catch (e) {}          try {              if (channelMap.containsKey(string)) {                  return $c(string);              }          } catch (e) {}          try {              if (sourceMap.containsKey(string)) {                  return $s(string);              }          } catch (e) {}          try {              if (globalChannelMap.containsKey(string)) {                  return $gc(string);              }          } catch (e) {}          try {              if (globalMap.containsKey(string)) {                  return $g(string);              }          } catch (e) {}          try {              if (configurationMap.containsKey(string)) {                  return $cfg(string);              }          } catch (e) {}          try {              if (resultMap.containsKey(string)) {                  return resultMap.get(string);              }          } catch (e) {}          return '';      }  function getAttachments() {          return AttachmentUtil.getMessageAttachments(connectorMessage);      }  function addAttachment(data, type) {          return AttachmentUtil.createAttachment(connectorMessage, data, type);      }  function validate(mapping, defaultValue, replacement) {          var result = mapping;          if ((result == undefined) || (result.toString().length == 0)) {              if (defaultValue == undefined) {                  defaultValue = '';              }              result = defaultValue;          }          if ('string' === typeof result || result instanceof java.lang.String || 'xml' === typeof result) {              result = new java.lang.String(result.toString());              if (replacement != undefined) {                  for (var i = 0; i < replacement.length; i++) {                      var entry = replacement[i];                      result = result.replaceAll(entry[0], entry[1]);                  }              }          }          return result;      }  function createSegment(name, msgObj, index) {          if (arguments.length == 1) {              return new XML('<' + name + '></' + name + '>');          };          if (arguments.length == 2) {              index = 0;          };          msgObj[name][index] = new XML('<' + name + '></' + name + '>');          return msgObj[name][index];      }  function createSegmentAfter(name, segment) {          var msgObj = segment;          while (msgObj.parent() != undefined) {  35       APPENDICES         msgObj = msgObj.parent();     }     msgObj.insertChildAfter(segment[0], new XML('<' + name + '></' + name + '>'));     return msgObj.child(segment[0].childIndex() + 1); } importClass = function() {     logger.error('The importClass method has been deprecated and will soon be removed. Please use importPackage or the fully-qualified class name instead.');     for each(argument in arguments) {         var className = new Packages.java.lang.String(argument);         if (className.startsWith('class ')) {             className = className.substring(6);         }         eval('importPackage(' + Packages.java.lang.Class.forName(className).getPackage().getName() + ')');     } }  function doScript() {     // Retrieve inbound message and defined 'msg' variable     msg = new XML(connectorMessage.getTransformedData());     if (msg.namespace('') != undefined) {         default xml namespace = msg.namespace('');     } else {         default xml namespace = '';     }  // User defined filter rule     function doFilter() {         phase[0] = 'filter';         return true;     }  function doTransform() {         phase[0] = 'transformer';         logger = Packages.org.apache.log4j.Logger.getLogger(phase[0]);  // User defined Source Connector Transformer         logger.info("Source Transformer script");   // If Inbound message template is defined         if ('xml' === typeof msg) {             if (msg.hasSimpleContent()) {                 msg = msg.toXMLString();             }         } else if ('undefined' !== typeof msg && msg !== null) {             var toStringResult = Object.prototype.toString.call(msg);             if (toStringResult == '[object Object]' || toStringResult == '[object Array]') {                 msg = JSON.stringify(msg);             }         }  // If Outbound message template is defined         if ('xml' === typeof tmp) {             if (tmp.hasSimpleContent()) {                 tmp = tmp.toXMLString();             }         } else if ('undefined' !== typeof tmp && tmp !== null) {             var toStringResult = Object.prototype.toString.call(tmp);             if (toStringResult == '[object Object]' || toStringResult == '[object Array]') {                 tmp = JSON.stringify(tmp);             }         }     }     if (doFilter() == true) {         doTransform();         return true;     } else {         return false;     } }  doScript();     APPENDICES          36      Channel Destination Connector script  function $co(key, value) {          if (arguments.length == 1) {              return connectorMap.get(key);          } else {              return connectorMap.put(key, value);          }      }  function $c(key, value) {          if (arguments.length == 1) {              return channelMap.get(key);          } else {              return channelMap.put(key, value);          }      }  function $s(key, value) {          if (arguments.length == 1) {              return sourceMap.get(key);          } else {              return sourceMap.put(key, value);          }      }  function $gc(key, value) {          if (arguments.length == 1) {              return globalChannelMap.get(key);          } else {              return globalChannelMap.put(key, value);          }      }  function $g(key, value) {          if (arguments.length == 1) {              return globalMap.get(key);          } else {              return globalMap.put(key, value);          }      }  function $cfg(key, value) {          if (arguments.length == 1) {              return configurationMap.get(key);          } else {              return configurationMap.put(key, value);          }      }  function $r(key, value) {          if (arguments.length == 1) {              return responseMap.get(key);          } else {              return responseMap.put(key, value);          }      }  function $(string) {          try {              if (responseMap.containsKey(string)) {                  return $r(string);              }          } catch (e) {}          try {              if (connectorMap.containsKey(string)) {                  return $co(string);              }          } catch (e) {}          try {              if (channelMap.containsKey(string)) {                  return $c(string);              }          } catch (e) {}          try {              if (sourceMap.containsKey(string)) {                  return $s(string);  37      APPENDICES         }     } catch (e) {}     try {         if (globalChannelMap.containsKey(string)) {             return $gc(string);         }     } catch (e) {}     try {         if (globalMap.containsKey(string)) {             return $g(string);         }     } catch (e) {}     try {         if (configurationMap.containsKey(string)) {             return $cfg(string);         }     } catch (e) {}     try {         if (resultMap.containsKey(string)) {             return resultMap.get(string);         }     } catch (e) {}     return ''; }  function getAttachments() {     return AttachmentUtil.getMessageAttachments(connectorMessage); }  function addAttachment(data, type) {     return AttachmentUtil.createAttachment(connectorMessage, data, type); }  function validate(mapping, defaultValue, replacement) {     var result = mapping;     if ((result == undefined) || (result.toString().length == 0)) {         if (defaultValue == undefined) {             defaultValue = '';         }         result = defaultValue;     }     if ('string' === typeof result || result instanceof java.lang.String || 'xml' === typeof result) {         result = new java.lang.String(result.toString());         if (replacement != undefined) {             for (var i = 0; i < replacement.length; i++) {                 var entry = replacement[i];                 result = result.replaceAll(entry[0], entry[1]);             }         }     }     return result; }  function createSegment(name, msgObj, index) {     if (arguments.length == 1) {         return new XML('<' + name + '></' + name + '>');     };     if (arguments.length == 2) {         index = 0;     };     msgObj[name][index] = new XML('<' + name + '></' + name + '>');     return msgObj[name][index]; }  function createSegmentAfter(name, segment) {     var msgObj = segment;     while (msgObj.parent() != undefined) {         msgObj = msgObj.parent();     }     msgObj.insertChildAfter(segment[0], new XML('<' + name + '></' + name + '>'));     return msgObj.child(segment[0].childIndex() + 1); } importClass = function() {     logger.error('The importClass method has been deprecated and will soon be removed. Please use importPackage or the fully-qualified class name instead.');     for each(argument in arguments) {         var className = new Packages.java.lang.String(argument);         if (className.startsWith('class ')) {             className = className.substring(6);  APPENDICES      38              }              eval('importPackage(' + Packages.java.lang.Class.forName(className).getPackage().getName() + ')');          }      }  function doScript() {  // Retrieve inbound message and defined 'msg' variable          msg = new XML(connectorMessage.getTransformedData());          if (msg.namespace('') != undefined) {              default xml namespace = msg.namespace('');          } else {              default xml namespace = '';          }  // User defined filter rule          function filterRule1() {              logger.info("This is the Destination Filter rule");          }  function doFilter() {              phase[0] = 'filter';              return ((filterRule1() == true));          }  function doTransform() {              phase[0] = 'transformer';              logger = Packages.org.apache.log4j.Logger.getLogger(phase[0]);   // User defined Destination Connector Transformer              logger.info("This is the Destination Transformer step");   // If Inbound message template is defined              if ('xml' === typeof msg) {                  if (msg.hasSimpleContent()) {                      msg = msg.toXMLString();                  }  } else if ('undefined' !== typeof msg && msg !== null) {                  var toStringResult = Object.prototype.toString.call(msg);                  if (toStringResult == '[object Object]' || toStringResult == '[object Array]') {                      msg = JSON.stringify(msg);                  }              }  // If Outbound message template is defined              if ('xml' === typeof tmp) {                  if (tmp.hasSimpleContent()) {                      tmp = tmp.toXMLString();                  }  } else if ('undefined' !== typeof tmp && tmp !== null) {                  var toStringResult = Object.prototype.toString.call(tmp);                  if (toStringResult == '[object Object]' || toStringResult == '[object Array]') {                      tmp = JSON.stringify(tmp);                  }              }          }  if (doFilter() == true) {              doTransform();              return true;          } else {              return false;          }  }  doScript();     39       APPENDICES H: Archives Content  There are five archives provided with this book each of which contains a complete set of     files required for Part II - Part V implementations.  Eligibility.NoACK  Folder              Files                                     Comment     Channels            Code Template.xml                         Channels, code templates and                         ConfigurationMap.properties               global scripts for Part II                         Data Logger.xml                           implementation.                         Global Script.xml                         HL7v3 Verification.xml                         Query Sender.xml                         Response Sender.xml                         v2-v3 Transformater.xml                         v3-v2 Transformater.xml     custom-lib          /coreschemas                              Custom-lib folder for Mirth Connect                         /schemas                                  Server installation.                         /schematron     DB                  PostgreSQL-Eligibility DB.sql             PostgreSQL patients database     HL7v2\Samples       QBP_E22_Request.hl7                         RSP_E22_Error.hl7                         RSP_E22_Success.hl7     HL7v2\Templates     RSP-45_Template.hl7     HL7v2\XSLT          QUCR-RSP.xslt     HL7v3               <intentionally skipped>                   Schemas for HL7v3 messages     HL7v3\-             QUCR_IN200101UV01_Request_Annotated.xml   Annotated Eligibility query response     Samples_Annotated   QUCR_IN210101UV01_Error_Annoteated.xml    and request messages                         QUCR_IN210101UV01_Success_Annotated.xml     HL7v3\Templates     QUCR_IN200101_Template.xml                Eligibility query response and                         QUCR_IN210101_Template.xml                request template messages with                                                                   empty fields   Eligibility.ACK-NACK  Folder              Files                                     Comment     Channels            Code Template ACK.xml                     Channels, code templates and                         ConfigurationMap.properties               global scripts for Part III                         Data Logger.xml                           implementation.                         Global Script.xml                         HL7v3 ACK.xml                         HL7v3 Verification-ACK.xml                         Query Sender-ACK.xml                         v2-v3 Transformer-ACK.xml     custom-lib          /coreschemas                              Custom-lib folder for Mirth Connect                         /schemas                                  Server installation.                         /schematron     DB                  PostgreSQL-Eligibility DB.sql             PostgreSQL patients database     HL7v2\Samples       ACK-A01_Negative.hl7                      HL7v2 acknowledgement samples  APPENDICES        40                          ACK-A01_Positive.hl7      HL7v3               <intentionally skipped>           Schemas for HL7v3 messages      HL7v3\Samples       MCCI_IN000002UV01.xml             HL7v3 acknowledgement sample      HL7v3\-             MCCI_IN000002UV01-Annotated.xml   HL7v2 acknowledgement sample      Samples_Annotated                                     with annotations      HL7v3\Templates     MCCI_IN000002_template.xml        HL7v2 acknowledgement template                                                            with empty fields   DICOM  Folder              Files                             Comment      Channels            Code Template.xml                 Channels, code templates and                          ConfigurationMap.properties       global scripts for Part IV                          DICOM SCP.xml                     implementation.                          DICOM SCU.xml                          Global Scripts.xml   Eligibility.JMS  Folder              Files                             Comment      Channels            Data Logger JMS.xml               Channels, code templates and                          Data Logger RAW.xml               global scripts for Part V                          HL7v3 Verification JMS.xml        implementation.                          HL7v3 Verification RAW.xml                          Query Sender JMS.xml                          v2-v3 Transformer JMS.xml                          v2-v3 Transformer RAW.xml      custom-lib          faultmessage.jar                  Custom-lib folder for Mirth Connect                                                            Server installation.   Debugging  Folder              Files                             Comment      JSDT                JavaScriptTask.java               Eclipse JSDT debugger in                                                            embedded mode.      Rhino Debugger      JavaScriptTask.java               Rhino JavaScript debugger in                                                            embedded mode.   Polling  Folder              Files                             Comment      Channels            IHE Validator Service.xml         Polling channels                          Web Service Polling.xml   Extension.JSON  Folder              Files                             Comment      Deploy              json/lib/org-json.jar             JSON Writer destination connector                          json/destination.xml              deployment package                          json/json-client.jar  41     APPENDICES                   json/json-server.jar                   json/json-shared.jar jarsigner         signjar.bat                          Batch file with command prompts                                                        to sign JARs Source\Client     JSONWriter.java                      Client side extension template Source\Server     destination.xml                      Server side extension templates                   JSONConnectorServlet.java                   JSONConnectorServletInterface.java                   JSONDispatcher.java                   JSONDispatcherProperties.java Source\org.json   JSONArray.java                       XML to JSON library source code                   JSONException.java                   JSONObject.java                   JSONString.java                   JSONStringer.java                   JSONTokener.java                   JSONWriter.java                   XML.java                   XMLTokener.java     APPENDICES      42