package cdac.medinfo.sdk.hl7282.hl7net.hl7system;



import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;

import cdac.medinfo.sdk.hl7282.baselibs.messagedictionary.MessageMapReader;
import cdac.medinfo.sdk.hl7282.baselibs.messages.ACK;
import cdac.medinfo.sdk.hl7282.baselibs.messages.AbstractQuery;
import cdac.medinfo.sdk.hl7282.baselibs.messages.Group;
import cdac.medinfo.sdk.hl7282.baselibs.messages.IMessageRecepient;
import cdac.medinfo.sdk.hl7282.baselibs.messages.IMessageSource;
import cdac.medinfo.sdk.hl7282.baselibs.messages.Message;
import cdac.medinfo.sdk.hl7282.baselibs.messages.MessageFactory;
import cdac.medinfo.sdk.hl7282.baselibs.parserserializer.HL7Serializer;
import cdac.medinfo.sdk.hl7282.baselibs.segments.ARQ;
import cdac.medinfo.sdk.hl7282.baselibs.segments.BHS;
import cdac.medinfo.sdk.hl7282.baselibs.segments.BTS;
import cdac.medinfo.sdk.hl7282.baselibs.segments.DSC;
import cdac.medinfo.sdk.hl7282.baselibs.segments.EQU;
import cdac.medinfo.sdk.hl7282.baselibs.segments.EVN;
import cdac.medinfo.sdk.hl7282.baselibs.segments.FHS;
import cdac.medinfo.sdk.hl7282.baselibs.segments.FTS;
import cdac.medinfo.sdk.hl7282.baselibs.segments.GOL;
import cdac.medinfo.sdk.hl7282.baselibs.segments.IVC;
import cdac.medinfo.sdk.hl7282.baselibs.segments.MFE;
import cdac.medinfo.sdk.hl7282.baselibs.segments.MFI;
import cdac.medinfo.sdk.hl7282.baselibs.segments.MSA;
import cdac.medinfo.sdk.hl7282.baselibs.segments.MSH;
import cdac.medinfo.sdk.hl7282.baselibs.segments.OBR;
import cdac.medinfo.sdk.hl7282.baselibs.segments.OBX;
import cdac.medinfo.sdk.hl7282.baselibs.segments.ORC;
import cdac.medinfo.sdk.hl7282.baselibs.segments.PID;
import cdac.medinfo.sdk.hl7282.baselibs.segments.PRD;
import cdac.medinfo.sdk.hl7282.baselibs.segments.PSG;
import cdac.medinfo.sdk.hl7282.baselibs.segments.PSS;
import cdac.medinfo.sdk.hl7282.baselibs.segments.PV1;
import cdac.medinfo.sdk.hl7282.baselibs.segments.QAK;
import cdac.medinfo.sdk.hl7282.baselibs.segments.QPD;
import cdac.medinfo.sdk.hl7282.baselibs.segments.RCP;
import cdac.medinfo.sdk.hl7282.baselibs.segments.RFI;
import cdac.medinfo.sdk.hl7282.baselibs.segments.RGS;
import cdac.medinfo.sdk.hl7282.baselibs.segments.SLT;
import cdac.medinfo.sdk.hl7282.baselibs.segments.STF;
import cdac.medinfo.sdk.hl7282.baselibs.segments.Segment;
import cdac.medinfo.sdk.hl7282.baselibs.segments.TXA;
import cdac.medinfo.sdk.hl7282.commoninterface.IGroup;
import cdac.medinfo.sdk.hl7282.commoninterface.ISegment;
import cdac.medinfo.sdk.hl7282.commoninterface.ISegmentSet;
import cdac.medinfo.sdk.hl7282.commoninterface.ISingleCollection;
import cdac.medinfo.sdk.hl7282.exceptions.InvalidMessageException;
import cdac.medinfo.sdk.hl7282.hl7model.messages.applicationmanagement.AppMgtRecepient;
import cdac.medinfo.sdk.hl7282.hl7model.messages.applicationmanagement.AppMgtSource;
import cdac.medinfo.sdk.hl7282.hl7model.messages.applicationmanagement.NMD_N02;
import cdac.medinfo.sdk.hl7282.hl7model.messages.claimsandreimbursement.ClaimsAndReimbursementRecepient;
import cdac.medinfo.sdk.hl7282.hl7model.messages.claimsandreimbursement.ClaimsAndReimbursementSource;
import cdac.medinfo.sdk.hl7282.hl7model.messages.claimsandreimbursement.EHC_E12;
import cdac.medinfo.sdk.hl7282.hl7model.messages.claimsandreimbursement.EHC_E13;
import cdac.medinfo.sdk.hl7282.hl7model.messages.claimsandreimbursement.QBP_E03;
import cdac.medinfo.sdk.hl7282.hl7model.messages.claimsandreimbursement.RSP_E03;
import cdac.medinfo.sdk.hl7282.hl7model.messages.clinicallaboratoryautomation.ClinicalLabAutoRecepient;
import cdac.medinfo.sdk.hl7282.hl7model.messages.clinicallaboratoryautomation.ClinicalLabAutoSource;
import cdac.medinfo.sdk.hl7282.hl7model.messages.clinicallaboratoryautomation.ESR_U02;
import cdac.medinfo.sdk.hl7282.hl7model.messages.financialmanagement.BAR_P12;
import cdac.medinfo.sdk.hl7282.hl7model.messages.financialmanagement.FinancialRecepient;
import cdac.medinfo.sdk.hl7282.hl7model.messages.financialmanagement.FinancialSource;
import cdac.medinfo.sdk.hl7282.hl7model.messages.masterfiles.MFN_M13;
import cdac.medinfo.sdk.hl7282.hl7model.messages.masterfiles.MasterFileRecepient;
import cdac.medinfo.sdk.hl7282.hl7model.messages.masterfiles.MasterFileSource;
import cdac.medinfo.sdk.hl7282.hl7model.messages.materialsmanagement.MaterialsMgtRecepient;
import cdac.medinfo.sdk.hl7282.hl7model.messages.materialsmanagement.MaterialsMgtSource;
import cdac.medinfo.sdk.hl7282.hl7model.messages.materialsmanagement.SLR_S28;
import cdac.medinfo.sdk.hl7282.hl7model.messages.medicalrecords.MDM_T01;
import cdac.medinfo.sdk.hl7282.hl7model.messages.medicalrecords.MediRecRecepient;
import cdac.medinfo.sdk.hl7282.hl7model.messages.medicalrecords.MediRecSource;
import cdac.medinfo.sdk.hl7282.hl7model.messages.observationreporting.ORU_R01;
import cdac.medinfo.sdk.hl7282.hl7model.messages.observationreporting.ObsvRepRecepient;
import cdac.medinfo.sdk.hl7282.hl7model.messages.observationreporting.ObsvRepSource;
import cdac.medinfo.sdk.hl7282.hl7model.messages.orderentry.OMG_O19;
import cdac.medinfo.sdk.hl7282.hl7model.messages.orderentry.OrderEntryRecepient;
import cdac.medinfo.sdk.hl7282.hl7model.messages.orderentry.OrderEntrySource;
import cdac.medinfo.sdk.hl7282.hl7model.messages.patientadministration.ADTRecepient;
import cdac.medinfo.sdk.hl7282.hl7model.messages.patientadministration.ADTSource;
import cdac.medinfo.sdk.hl7282.hl7model.messages.patientadministration.ADT_A01;
import cdac.medinfo.sdk.hl7282.hl7model.messages.patientadministration.ADT_A02;
import cdac.medinfo.sdk.hl7282.hl7model.messages.patientadministration.QBP_Q21;
import cdac.medinfo.sdk.hl7282.hl7model.messages.patientadministration.RSP_K21;
import cdac.medinfo.sdk.hl7282.hl7model.messages.patientcare.PGL_PC6;
import cdac.medinfo.sdk.hl7282.hl7model.messages.patientcare.PatientCareRecepient;
import cdac.medinfo.sdk.hl7282.hl7model.messages.patientcare.PatientCareSource;
import cdac.medinfo.sdk.hl7282.hl7model.messages.patientreferral.PatientRefRecepient;
import cdac.medinfo.sdk.hl7282.hl7model.messages.patientreferral.PatientRefSource;
import cdac.medinfo.sdk.hl7282.hl7model.messages.patientreferral.RQI_I01;
import cdac.medinfo.sdk.hl7282.hl7model.messages.personnelmanagement.PMU_B01;
import cdac.medinfo.sdk.hl7282.hl7model.messages.personnelmanagement.PersonalMgmtRecepient;
import cdac.medinfo.sdk.hl7282.hl7model.messages.personnelmanagement.PersonalMgmtSource;
import cdac.medinfo.sdk.hl7282.hl7model.messages.query.QryRecepient;
import cdac.medinfo.sdk.hl7282.hl7model.messages.query.QrySource;
import cdac.medinfo.sdk.hl7282.hl7model.messages.scheduling.SRM_S01;
import cdac.medinfo.sdk.hl7282.hl7model.messages.scheduling.SchedulingRecepient;
import cdac.medinfo.sdk.hl7282.hl7model.messages.scheduling.SchedulingSource;
import cdac.medinfo.sdk.hl7282.hl7net.auxiliaryprotocol.batch.BatchAgent;
import cdac.medinfo.sdk.hl7282.hl7net.auxiliaryprotocol.batch.HL7Batch;
import cdac.medinfo.sdk.hl7282.hl7net.auxiliaryprotocol.batch.HL7BatchFile;
import cdac.medinfo.sdk.hl7282.hl7net.auxiliaryprotocol.fragment.FragmentAgent;
import cdac.medinfo.sdk.hl7282.hl7net.auxiliaryprotocol.transactionhandler.TransactionHandler;
import cdac.medinfo.sdk.hl7282.hl7net.commons.IBatchProcessor;
import cdac.medinfo.sdk.hl7282.hl7net.commons.IFragmentProcessor;
import cdac.medinfo.sdk.hl7282.hl7net.commons.IHL7Batch;
import cdac.medinfo.sdk.hl7282.hl7net.commons.IHL7BatchFile;
import cdac.medinfo.sdk.hl7282.hl7net.commons.ITransactionHandler;
import cdac.medinfo.sdk.hl7282.hl7net.localextension.Populate_Test;
import cdac.medinfo.sdk.hl7282.hl7net.upperlayer.ClientSession;
import cdac.medinfo.sdk.hl7282.hl7net.upperlayer.IBatchReceiver;
import cdac.medinfo.sdk.hl7282.hl7net.upperlayer.IExceptionListener;
import cdac.medinfo.sdk.hl7282.hl7net.upperlayer.IProcessHandler;
import cdac.medinfo.sdk.hl7282.hl7net.upperlayer.ServerSession;
import cdac.medinfo.sdk.hl7282.hl7net.upperlayer.UserSession;
import cdac.medinfo.sdk.hl7282.utils.EnumMessageCode;
import cdac.medinfo.sdk.hl7282.utils.EnumMessageStructure;
import cdac.medinfo.sdk.hl7282.utils.EnumSegments;
import cdac.medinfo.sdk.hl7282.utils.EnumTriggerEvent;
import cdac.medinfo.sdk.hl7282.utils.HL7Config;
import cdac.medinfo.sdk.hl7282.utils.IMap;
import cdac.medinfo.sdk.hl7282.utils.IMessageMapReader;
import cdac.medinfo.sdk.hl7282.utils.SingleCollection;
import cdac.medinfo.sdk.hl7282.utils.StandardMethods;

/**
 * This sample code demonstrates implementation of Server and Client for HL7System.
 * HL7System  has following capabilities
 * 1)Send Query,Event,Batch and BatchFile,ACK for Response received by creating Separate User Session.  
 * 2)Receive Response,ACK for Sent Queries,Event,Batch and Batch File.
 * 3)Send Response,ACK for Received Queries,Event,Batch and Batch File.   
 * 4)Receive Query,Event,Batch and BatchFile,ACK for Response received by creating Separate Server Session.
 * the network provided it has knowledge of other systems. 
 */
public class HL7System implements IExceptionListener,IBatchReceiver
{
	String strMsgControlID =null;
	private int MsgControlID = 0,i=0;
	UserSession objUserSession =null;
	String strQueryId = null;
	private Populate_Test objPopulateTest = new Populate_Test();
	ISingleCollection<Message> objDeferredMessageCollection = new SingleCollection<Message>();
	ITransactionHandler objServerTransactionHandler = null;
	
	/**
	 * @param args
	 */
	public static void main(String[] args) 
	{
		try
		{
			/*
			 * Specifying logging directory.
			 * User can specify any directory where log files will be created.
			 * If no path is specified then logs will be generated in user's temp directory. 
			 */
			HL7Config.createInstance().enableLogging("E:\\HL7System_Logs");

			
			//Instantiating HL7System. 
			HL7System objHL7System = new HL7System();

			//Creating Server Session for HL7System separately for processing queries,Events,batch and batch file. 
			objHL7System.createServerSesssion();

			//Creating User Session for HL7System separately for processing queries,Events,batch and batch file. 
			objHL7System.createUserSesssion();
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
	}
	private void createUserSesssion()
	{
		try
		{

			//This will wait for some time to perform IO operation for Server Session to take ip and port and start Server Session.
			Thread.sleep(39999);

			

			//Creating User Session for HL7System.
			objUserSession = new UserSession();

			//Create MessageFactory to provide support for creation and population of messages.
			MessageFactory objMessageFactory = MessageFactory.createInstance();


			/*   Patient Administration System */
			/*
			 * Instantiating Message Recipient for HL7System
			 * User can provide his own implementation of Message Recipient by implementing IMessageReceipient interface. 
			 */
			IMessageRecepient objADTRecepient = new ADTRecepient();

			/*
			 * Adding Patient Admin Recipient on Message Factory.
			 * By setting this recipient client becomes capable to create messages and send Events of Patient Admin System
			 * Similarly user can set recipients for different systems.
			 * sdk for HL7 provides sources for all systems specified by HL7.
			 */ 
			objMessageFactory.addMessageRecepient(objADTRecepient);

			/*
			 * Instantiating Message Source for HL7System
			 * User can provide his own implementation of Message Source by implementing IMessageSource interface. 
			 */
			IMessageSource objADTSource  = new ADTSource();

			/*
			 * Adding Patient Admin Source and Recipient on on Message Factory.
			 * By setting this source client becomes capable to create messages and receive responses of Patient Admin System
			 * Similarly user can set sources for different systems.
			 * sdk for HL7 provides sources for all systems specified by HL7.
			 */ 
			objMessageFactory.addMessageSource(objADTSource);


			/*   Query System */
			//Initiating Message Recipient for Query System.
			IMessageRecepient objQryRecepient = new QryRecepient();

			//Add the Message Recipient in MessageFactory.
			objMessageFactory.addMessageRecepient(objQryRecepient);

			//Initiating Message Source for Query System.
			IMessageSource objQrySource  = new QrySource();

			//Add MessageRecipient to MessageFactory.
			objMessageFactory.addMessageSource(objQrySource);

			/* 
			 * As per the given systems requirement Un-Comment required source and 
			 * Recipient for sending and receiving for supported messages.  */

		   // Application management System 
			//Initiating Message Recipient for Application management System.
			IMessageRecepient objAppMgtRecepient = new AppMgtRecepient();

			//Add the Message Recipient in MessageFactory.
			objMessageFactory.addMessageRecepient(objAppMgtRecepient);

			//Initiating Message Source for Application management System.
			IMessageSource objAppMgtSource  = new AppMgtSource();

			//Add MessageRecipient to MessageFactory.
			objMessageFactory.addMessageSource(objAppMgtSource);


			 //  Clinical Laboratory Automation System 
			//Initiating Message Recipient for Clinical Laboratory Automation System.
			IMessageRecepient objClinicalLabAutoRecepient = new ClinicalLabAutoRecepient();

			//Add the Message Recipient in MessageFactory.
			objMessageFactory.addMessageRecepient(objClinicalLabAutoRecepient);

			//Initiating Message Source for Clinical Laboratory Automation System.
			IMessageSource objClinicalLabAutoSource  = new ClinicalLabAutoSource();

			//Add MessageRecipient to MessageFactory.
			objMessageFactory.addMessageSource(objClinicalLabAutoSource);


			 //  Financial Management System 
			//Initiating Message Recipient for Financial Management System.
			IMessageRecepient objFinancialRecepient = new FinancialRecepient();

			//Add the Message Recipient in MessageFactory.
			objMessageFactory.addMessageRecepient(objFinancialRecepient);

			//Initiating Message Source for Financial Management System.
			IMessageSource objFinancialSource  = new FinancialSource();

			//Add MessageRecipient to MessageFactory.
			objMessageFactory.addMessageSource(objFinancialSource);


			 //  Master Files System 
			//Initiating Message Recipient for Master Files System.
			IMessageRecepient objMasterFileRecepient = new MasterFileRecepient();

			//Add the Message Recipient in MessageFactory.
			objMessageFactory.addMessageRecepient(objMasterFileRecepient);

			//Initiating Message Source for Master Files System.
			IMessageSource objMasterFileSource  = new MasterFileSource();

			//Add MessageRecipient to MessageFactory.
			objMessageFactory.addMessageSource(objMasterFileSource);


			 //  Medical Records System 
			//Initiating Message Recipient for Medical Records System.
			IMessageRecepient objMediRecRecepient = new MediRecRecepient();

			//Add the Message Recipient in MessageFactory.
			objMessageFactory.addMessageRecepient(objMediRecRecepient);

			//Initiating Message Source for Medical Records System.
			IMessageSource objMediRecSource  = new MediRecSource();

			//Add MessageRecipient to MessageFactory.
			objMessageFactory.addMessageSource(objMediRecSource);


			//  Observation Reporting System 
			//Initiating Message Recipient for Observation Reporting System.
			IMessageRecepient objObsvRepRecepient = new ObsvRepRecepient();

			//Add the Message Recipient in MessageFactory.
			objMessageFactory.addMessageRecepient(objObsvRepRecepient);

			//Initiating Message Source for Observation Reporting System.
			IMessageSource objObsvRepSource  = new ObsvRepSource();

			//Add MessageRecipient to MessageFactory.
			objMessageFactory.addMessageSource(objObsvRepSource);


			 // Order Entry System 
			//Initiating Message Recipient for Order Entry System.
			IMessageRecepient objOrderEntryRecepient = new OrderEntryRecepient();

			//Add the Message Recipient in MessageFactory.
			objMessageFactory.addMessageRecepient(objOrderEntryRecepient);

			//Initiating Message Source for Order Entry System.
			IMessageSource objOrderEntrySource  = new OrderEntrySource();

			//Add MessageRecipient to MessageFactory.
			objMessageFactory.addMessageSource(objOrderEntrySource);


			 // Patient Care System 
			//Initiating Message Recipient for Patient Care System.
			IMessageRecepient objPatientCareRecepient = new PatientCareRecepient();

			//Add the Message Recipient in MessageFactory.
			objMessageFactory.addMessageRecepient(objPatientCareRecepient);

			//Initiating Message Source for Patient Care System.
			IMessageSource objPatientCareSource  = new PatientCareSource();

			//Add MessageRecipient to MessageFactory.
			objMessageFactory.addMessageSource(objPatientCareSource);


			 // Patient Referral System 
			//Initiating Message Recipient for Patient Referral System.
			IMessageRecepient objPatientRefRecepient = new PatientRefRecepient();

			//Add the Message Recipient in MessageFactory.
			objMessageFactory.addMessageRecepient(objPatientRefRecepient);

			//Initiating Message Source for Patient Referral System.
			IMessageSource objPatientRefSource  = new PatientRefSource();

			//Add MessageRecipient to MessageFactory.
			objMessageFactory.addMessageSource(objPatientRefSource);


			 // Personnel Management System 
			//Initiating Message Recipient for Personnel Management System.
			IMessageRecepient objPersonalMgmtRecepient = new PersonalMgmtRecepient();

			//Add the Message Recipient in MessageFactory.
			objMessageFactory.addMessageRecepient(objPersonalMgmtRecepient);

			//Initiating Message Source for Personnel Management System.
			IMessageSource objPersonalMgmtSource  = new PersonalMgmtSource();

			//Add MessageRecipient to MessageFactory.
			objMessageFactory.addMessageSource(objPersonalMgmtSource);


			 // Scheduling System 
			//Initiating Message Recipient for Scheduling System.
			IMessageRecepient objSchedulingRecepient = new SchedulingRecepient();

			//Add the Message Recipient in MessageFactory.
			objMessageFactory.addMessageRecepient(objSchedulingRecepient);

			//Initiating Message Source for Scheduling System.
			IMessageSource objSchedulingSource  = new SchedulingSource();

			//Add Message Source to MessageFactory.
			objMessageFactory.addMessageSource(objSchedulingSource);

			
			//Materials Management
			//Initiating Message Recipient for Material Management System.
			IMessageRecepient objMaterialsMgtRecepient = new MaterialsMgtRecepient();
			
			//Add the Message Recipient in MessageFactory.
			objMessageFactory.addMessageRecepient(objMaterialsMgtRecepient);
			
			//Initiating Message Source for Materials management system.
			IMessageSource objMaterialsMgtSource = new MaterialsMgtSource();
			
			//Add the Message source in MessageFactory.
			objMessageFactory.addMessageSource(objMaterialsMgtSource);
			
			
			//Claims And Reimbursement
			//Initiating Message Recipient for Claims And Reimbursement System.
			IMessageRecepient objClaimsAndReimbursementRecepient = new ClaimsAndReimbursementRecepient();
			
			//Add the Message Recipient in MessageFactory.
			objMessageFactory.addMessageRecepient(objClaimsAndReimbursementRecepient);
			
			//Initiating Message Source for Claims And Reimbursement System.
			IMessageSource objClaimsAndReimbursementSource = new ClaimsAndReimbursementSource();
			
			//Add the Message Source in MessageFactory.
			objMessageFactory.addMessageSource(objClaimsAndReimbursementSource);
			

			
			/*
			 * Instantiating IFragmentProcessor which handles the fragmentation and defragmention for larger messages.
			 * FragmentAgent is the default implementation provided by sdk for HL7.
			 * User can provide his own implementation for FragmentProcessor by implementing IFragmentProcessor interface.
			 */ 
			IFragmentProcessor objIFragmentProcessor = new FragmentAgent();

			//Setting Fragment processor on user session.
			objUserSession.setFragmentProcessor(objIFragmentProcessor);

			/*
			 * Instantiating IBatchProcessor which handles HL7Batch and HL7BatchFiles.
			 * BatchAgent is the default implementation provided by SDK for HL7.
			 * User can provide his own implementation for BatchProcessor by implementing IBatchProcessor interface.
			 */
			IBatchProcessor objIBatchProcessor = new BatchAgent();

			//Setting Batch Processor on user session
			objUserSession.setBatchProcessor(objIBatchProcessor);
			
			/*
			 * Instantiating TransactionHandler which keeps track for the sending and receiving message 
			 * and does verification of each message during transaction.
			 * User can provide his own implementation for ClientSideTransactionHandler by implementing ITransactionHandler interface.
			 * if user wants verification for each message within transaction then user has to set it else not.
			 */
			ITransactionHandler objClientSideTransactionHandler = new TransactionHandler();
			
			//Setting this transaction handler on User session.
			objUserSession.setClientSideTransactionHandler(objClientSideTransactionHandler);
			
			/*
			 * Setting the class implementing behavior of HL7System as listener in asynchronous mode,
			 * to process deferred queries.
			 * User can provide his own implementation by implementing interface IAsynReceiver
			 */
			objUserSession.addExceptionListener(this);

			/*
			 * Returns received HL7BatchFile .
			 * User can provide his own implementation by implementing interface IBatchReceiver.
			 */
			objUserSession.setIBatchReceiver((IBatchReceiver)this);

			//Reading IP address for HL7System
			System.out.println("Enter IP Adderess of HL7System : ");
			InputStreamReader input = new InputStreamReader(System.in);
			BufferedReader reader = new BufferedReader(input);
			String strIP = reader.readLine();
			//Reading port for HL7System
			System.out.println("Enter Port on which HL7System is listening : ");
			String strPort = reader.readLine();
			int port = Integer.parseInt(strPort);

			//Connecting this client with HL7System.
			objUserSession.connect(strIP, port);

			executeUserOption();

			System.out.println("Ending Client..");
			objUserSession.close();
		}
		catch (Exception e)
		{
			System.out.println("Error Ocured (Ending Client..)== > "+e.getMessage());
			e.printStackTrace();
		}
	}
	/**
	 * Get choice from user.
	 * @return
	 */
	private int getChoice()
	{
		System.out.println("Enter your choice to send PatientAdministration Messages:   ");
		System.out.println("1. Simple ADT Event (ADT_A02) populate manually");
		System.out.println("2. Simple Immediate Query (QRY_A19) populate manually");
		System.out.println("3. Simple Deferred Query (QRY_A19) populate manually");
		System.out.println("4. Batch File With ADT and Query Batches populate manually");
		System.out.println("5. Simple NMD Event (NMD_N02) populate manually");
		System.out.println("6. Simple BAR Event (BAR_P12) populate manually");
		System.out.println("7. Simple Clinical Lab automation event (ESR_U02) populate manually");
		System.out.println("8. Simple MFN Event (MFN_M13) populate manually");
		System.out.println("9. Simple MDM Event (MDM_T01) populate manually");
		System.out.println("10. Simple OMG Event (OMG_O19) populate manually");
		System.out.println("11. Simple PGL Event (PGL_PC6) populate manually");
		System.out.println("12. Simple PMU Event (PMU_B01) populate manually");
		System.out.println("13. Simple SRM Event (SRM_S01) populate manually");
		System.out.println("14. Simple RQI Event (RQI_I01) populate manually");
		System.out.println("15. Simple ORU Event (ORU_R01) populate manually");
		System.out.println("16. Simple SLR Event (SLR_S28) populate manually");
		System.out.println("17. Simple QBP Event (QBP_E03) populate manually");
		
		InputStreamReader input = new InputStreamReader(System.in);
		BufferedReader reader = new BufferedReader(input);
		String strChoice = null;
		try
		{
			strChoice = reader.readLine();
			return Integer.parseInt(strChoice);
		}
		catch(IOException ioe)
		{
			ioe.printStackTrace();
		}
		catch (NumberFormatException nfe) 
		{
			System.out.println(nfe.getMessage());
		}
		return 0;
	}
	/*
	 * This method executes user option one by one.
	 */
	private void executeUserOption()
	{
		try
		{
			boolean bContinue = true;
			/*
			 * loop for getting choice from user, and accordingly doing operations.
			 */
			while(bContinue)
			{
				InputStreamReader inputRead = new InputStreamReader(System.in);
				BufferedReader readerRead = new BufferedReader(inputRead);
				int iChoice = getChoice();
				if(iChoice>=1 && iChoice<=17)
				{
					onChoice(iChoice, null);
						
					System.out.println("Do you want to continue..(Y/N)");
					char ch = (char)readerRead.read();
					if(ch=='y' || ch=='Y')
						bContinue = true;
					else if(ch=='n' || ch=='N')
						bContinue = false;
					else
					{
						System.out.println("Invalid Choice...");
					}
				}
				else
				{
					System.out.println("Invalid Choice...");
				}
			}
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
	}

	/**
	 * performs the operations as par the choice of user.
	 * @param iChoice
	 * @param strFilePath
	 */
	private void onChoice(int iChoice,String strFilePath)
	{
		try
		{
			switch (iChoice) 
			{
			case 1: // Create ADT A02 Message and then Send
				objUserSession.sendMessage(getADTA01());
				/*
				 * User can get Acknowledgment received from remote Server .This is demonstrated below.
				 * Acknowledgment message received  contains Acknowledgment for Transfer Patient Event (ADT_A02) sent.
				 * This is how we receive Acknowledgment for event.
				 */
				Thread.sleep(6000);
				
				ISingleCollection<Message> ackCollection = objUserSession.getRecievedMessagesCollection(strMsgControlID);
				if(ackCollection != null)
				{
					for(Message objMessage :ackCollection)
					{
						if(objMessage.getMessageStructure().equals(EnumMessageStructure.ACK.getValue()))
						{
							ACK ackMessage = (ACK)objMessage;
							System.out.println("ACK Received for event :: " + ackMessage.getTriggerEvent());
						}
						else
						{
							System.out.println("Response Received for event :: "+objMessage.getMessageCode()+"_" + objMessage.getTriggerEvent());
						}
					}
				}
				else
					System.out.println("ACK Collection is empty");
				break;
			case 2: 
				// Create QBP_Q21 with immediate priority Query and then Send.
				
				objUserSession.sendMessage(getQBPQ21("I"));
				/*
				 * User can get Response received from remote Server .This is demonstrated below.
				 * Response message received for QBP_Q21 sent.
				 */
				Thread.sleep(6000);
				
				ISingleCollection<Message> DeferredResponseCollection = objUserSession.getRecievedMessagesCollection(strMsgControlID);
				if(DeferredResponseCollection != null)
				{
					for(Message objMessage :DeferredResponseCollection)
					{
						System.out.println("Response Received for event :: " + objMessage.getTriggerEvent());
					}
					
				}
				else
					System.out.println("Response Collection is empty");
				break;	
			case 3:
				// Create QBP_Q21 with Deferred priority Query and then Send.
				
				objUserSession.sendMessage(getQBPQ21("D"));
				
				/*
				 * User can get Acknowledgment received from remote Server .This is demonstrated below.
				 * Acknowledgment message received  contains Acknowledgment for QBP_Q21 sent.
				 * This is how we receive Acknowledgment for Deferred Query.
				 */
				Thread.sleep(6000);
				
				ISingleCollection<Message> DeferredackCollection = objUserSession.getRecievedMessagesCollection(strMsgControlID);
				if(DeferredackCollection != null)
				{
					for(Message objMessage :DeferredackCollection)
					{
						if(objMessage.getMessageStructure().equals(EnumMessageStructure.ACK.getValue()))
						{
							ACK ackMessage = (ACK)objMessage;
							System.out.println("ACK Received for event :: " + ackMessage.getTriggerEvent());
						}
						else
						{
							System.out.println("Response Received for event :: "+objMessage.getMessageCode()+"_" + objMessage.getTriggerEvent());
						}
					}
				}
				else
					System.out.println("ACK Collection is empty");
				break;
			case 4:// Create BatchFile
				objUserSession.sendBatchFile(getADT_QRY_A19BatchFile());

				Thread.sleep(6000);
				
				ISingleCollection<IHL7BatchFile> objACKBatchCollectionForFile = objUserSession.getResponseBatches();

				if(objACKBatchCollectionForFile != null)
				{
					for(IHL7BatchFile objBatchFromFile : objACKBatchCollectionForFile)
					{
						ISingleCollection<IHL7Batch> objhl7batch = objBatchFromFile.getHL7BatchCollection();

						for(IHL7Batch objIHL7Batch :objhl7batch)
						{
							System.out.println("ACK Received for Batch :: " + objIHL7Batch.getBatchControlID());
						}
					}
				}
				else
					System.out.println("ACK Collection is empty");
				break;
			case 5: // Create NMD_N02 Message and then Send
				objUserSession.sendMessage(getNMDN02());
				/*
				 * User can get Acknowledgment received from remote Server .This is demonstrated below.
				 * Acknowledgment message received  contains Acknowledgment for Event (NMD_N02) sent.
				 * This is how we receive Acknowledgment for event.
				 */
				Thread.sleep(6000);
				
				ISingleCollection<Message> ackCollectionForApp = objUserSession.getRecievedMessagesCollection(strMsgControlID);
				if(ackCollectionForApp != null)
				{
					for(Message objMessage :ackCollectionForApp)
					{
						if(objMessage.getMessageStructure().equals(EnumMessageStructure.ACK.getValue()))
						{
							ACK ackMessage = (ACK)objMessage;
							System.out.println("ACK Received for event :: " + ackMessage.getTriggerEvent());
						}
						else
						{
							System.out.println("Response Received for event :: "+objMessage.getMessageCode()+"_" + objMessage.getTriggerEvent());
						}
					}
				}
				else
					System.out.println("ACK Collection is empty");
				break;
				
			case 6: // Create BAR_P12 Message and then Send
				objUserSession.sendMessage(getBARP12());
				/*
				 * User can get Acknowledgment received from remote Server .This is demonstrated below.
				 * Acknowledgment message received  contains Acknowledgment for Event (BAR_P12) sent.
				 * This is how we receive Acknowledgment for event.
				 */
				Thread.sleep(6000);
				
				ISingleCollection<Message> ackCollectionForFinancialMgt = objUserSession.getRecievedMessagesCollection(strMsgControlID);
				if(ackCollectionForFinancialMgt != null)
				{
					for(Message objMessage :ackCollectionForFinancialMgt)
					{
						if(objMessage.getMessageStructure().equals(EnumMessageStructure.ACK.getValue()))
						{
							ACK ackMessage = (ACK)objMessage;
							System.out.println("ACK Received for event :: " + ackMessage.getTriggerEvent());
						}
						else
						{
							System.out.println("Response Received for event :: "+objMessage.getMessageCode()+"_" + objMessage.getTriggerEvent());
						}
					}
				}
				else
					System.out.println("ACK Collection is empty");
				break;
				
			case 7: // Create ESR_U02 Message and then Send
				objUserSession.sendMessage(getESR_U02());
				/*
				 * User can get Acknowledgment received from remote Server .This is demonstrated below.
				 * Acknowledgment message received  contains Acknowledgment for Event (ESR_U02) sent.
				 * This is how we receive Acknowledgment for event.
				 */
				Thread.sleep(6000);
				
				ISingleCollection<Message> ackCollectionForClinicalLab = objUserSession.getRecievedMessagesCollection(strMsgControlID);
				if(ackCollectionForClinicalLab != null)
				{
					for(Message objMessage :ackCollectionForClinicalLab)
					{
						if(objMessage.getMessageStructure().equals(EnumMessageStructure.ACK.getValue()))
						{
							ACK ackMessage = (ACK)objMessage;
							System.out.println("ACK Received for event :: " + ackMessage.getTriggerEvent());
						}
						else
						{
							System.out.println("Response Received for event :: "+objMessage.getMessageCode()+"_" + objMessage.getTriggerEvent());
						}
					}
				}
				else
					System.out.println("ACK Collection is empty");
				break;
			case 8: // Create MFN_M13 Message and then Send
				objUserSession.sendMessage(getMFN_M13());
				/*
				 * User can get Acknowledgment received from remote Server .This is demonstrated below.
				 * Acknowledgment message received  contains Acknowledgment for Event (MFN_M13) sent.
				 * This is how we receive Acknowledgment for event.
				 */
				Thread.sleep(6000);
				
				ISingleCollection<Message> ackCollectionForMasterFiles = objUserSession.getRecievedMessagesCollection(strMsgControlID);
				if(ackCollectionForMasterFiles != null)
				{
					for(Message objMessage :ackCollectionForMasterFiles)
					{
						if(objMessage.getMessageStructure().equals(EnumMessageStructure.ACK.getValue()))
						{
							ACK ackMessage = (ACK)objMessage;
							System.out.println("ACK Received for event :: " + ackMessage.getTriggerEvent());
						}
						else
						{
							System.out.println("Response Received for event :: "+objMessage.getMessageCode()+"_" + objMessage.getTriggerEvent());
						}
					}
				}
				else
					System.out.println("ACK Collection is empty");
				break;
				
			case 9: // Create MDM_T01 Message and then Send
				objUserSession.sendMessage(getMDM_T01());
				/*
				 * User can get Acknowledgment received from remote Server .This is demonstrated below.
				 * Acknowledgment message received  contains Acknowledgment for Event (MDM_T01) sent.
				 * This is how we receive Acknowledgment for event.
				 */
				Thread.sleep(6000);
				
				ISingleCollection<Message> ackCollectionForMediRecords = objUserSession.getRecievedMessagesCollection(strMsgControlID);
				if(ackCollectionForMediRecords != null)
				{
					for(Message objMessage :ackCollectionForMediRecords)
					{
						if(objMessage.getMessageStructure().equals(EnumMessageStructure.ACK.getValue()))
						{
							ACK ackMessage = (ACK)objMessage;
							System.out.println("ACK Received for event :: " + ackMessage.getTriggerEvent());
						}
						else
						{
							System.out.println("Response Received for event :: "+objMessage.getMessageCode()+"_" + objMessage.getTriggerEvent());
						}
					}
				}
				else
					System.out.println("ACK Collection is empty");
				break;
				
			case 10: // Create OMG_O19 Message and then Send
				objUserSession.sendMessage(getOMG_O19());
				/*
				 * User can get Acknowledgment received from remote Server .This is demonstrated below.
				 * Acknowledgment message received  contains Acknowledgment for Event (OMG_O19) sent.
				 * This is how we receive Acknowledgment for event.
				 */
				Thread.sleep(6000);
				
				ISingleCollection<Message> ackCollectionForOrderEntry = objUserSession.getRecievedMessagesCollection(strMsgControlID);
				if(ackCollectionForOrderEntry != null)
				{
					for(Message objMessage :ackCollectionForOrderEntry)
					{
						if(objMessage.getMessageStructure().equals(EnumMessageStructure.ACK.getValue()))
						{
							ACK ackMessage = (ACK)objMessage;
							System.out.println("ACK Received for event :: " + ackMessage.getTriggerEvent());
						}
						else
						{
							System.out.println("Response Received for event :: "+objMessage.getMessageCode()+"_" + objMessage.getTriggerEvent());
						}
					}
				}
				else
					System.out.println("ACK Collection is empty");
				break;
				
			case 11: // Create PGL_PC6 Message and then Send
				objUserSession.sendMessage(getPGL_R30());
				/*
				 * User can get Acknowledgment received from remote Server .This is demonstrated below.
				 * Acknowledgment message received  contains Acknowledgment for Event (PGL_PC6) sent.
				 * This is how we receive Acknowledgment for event.
				 */
				Thread.sleep(6000);
				
				ISingleCollection<Message> ackCollectionForPatientCare = objUserSession.getRecievedMessagesCollection(strMsgControlID);
				if(ackCollectionForPatientCare != null)
				{
					for(Message objMessage :ackCollectionForPatientCare)
					{
						if(objMessage.getMessageStructure().equals(EnumMessageStructure.ACK.getValue()))
						{
							ACK ackMessage = (ACK)objMessage;
							System.out.println("ACK Received for event :: " + ackMessage.getTriggerEvent());
						}
						else
						{
							System.out.println("Response Received for event :: "+objMessage.getMessageCode()+"_" + objMessage.getTriggerEvent());
						}
					}
				}
				else
					System.out.println("ACK Collection is empty");
				break;
				
			case 12: // Create PMU_B01 Message and then Send
				objUserSession.sendMessage(getPMU_B01());
				/*
				 * User can get Acknowledgment received from remote Server .This is demonstrated below.
				 * Acknowledgment message received  contains Acknowledgment for Event (PMU_B01) sent.
				 * This is how we receive Acknowledgment for event.
				 */
				Thread.sleep(6000);
				
				ISingleCollection<Message> ackCollectionForPersMngmt = objUserSession.getRecievedMessagesCollection(strMsgControlID);
				if(ackCollectionForPersMngmt != null)
				{
					for(Message objMessage :ackCollectionForPersMngmt)
					{
						if(objMessage.getMessageStructure().equals(EnumMessageStructure.ACK.getValue()))
						{
							ACK ackMessage = (ACK)objMessage;
							System.out.println("ACK Received for event :: " + ackMessage.getTriggerEvent());
						}
						else
						{
							System.out.println("Response Received for event :: "+objMessage.getMessageCode()+"_" + objMessage.getTriggerEvent());
						}
					}
				}
				else
					System.out.println("ACK Collection is empty");
				break;
				
			case 13: // Create SRM_S01 Message and then Send
				objUserSession.sendMessage(getSRM_S01());
				/*
				 * User can get Acknowledgment received from remote Server .This is demonstrated below.
				 * Acknowledgment message received  contains Acknowledgment for Event (SRM_S01) sent.
				 * This is how we receive Acknowledgment for event.
				 */
				Thread.sleep(6000);
				
				ISingleCollection<Message> ackCollectionForScheduling = objUserSession.getRecievedMessagesCollection(strMsgControlID);
				if(ackCollectionForScheduling != null)
				{
					for(Message objMessage :ackCollectionForScheduling)
					{
						if(objMessage.getMessageStructure().equals(EnumMessageStructure.ACK.getValue()))
						{
							ACK ackMessage = (ACK)objMessage;
							System.out.println("ACK Received for event :: " + ackMessage.getTriggerEvent());
						}
						else
						{
							System.out.println("Response Received for event :: "+objMessage.getMessageCode()+"_" + objMessage.getTriggerEvent());
						}
					}
				}
				else
					System.out.println("ACK Collection is empty");
				break;
				
			case 14: // Create RQI_I01 Message and then Send
				objUserSession.sendMessage(getRQI_I01());
				/*
				 * User can get Acknowledgment received from remote Server .This is demonstrated below.
				 * Acknowledgment message received  contains Acknowledgment for Event (RQI_I01) sent.
				 * This is how we receive Acknowledgment for event.
				 */
				Thread.sleep(6000);
				
				ISingleCollection<Message> ackCollectionForPatientReferral = objUserSession.getRecievedMessagesCollection(strMsgControlID);
				if(ackCollectionForPatientReferral != null)
				{
					for(Message objMessage :ackCollectionForPatientReferral)
					{
						if(objMessage.getMessageStructure().equals(EnumMessageStructure.ACK.getValue()))
						{
							ACK ackMessage = (ACK)objMessage;
							System.out.println("ACK Received for event :: " + ackMessage.getTriggerEvent());
						}
						else
						{
							System.out.println("Response Received for event :: "+objMessage.getMessageCode()+"_" + objMessage.getTriggerEvent());
						}
					}
				}
				else
					System.out.println("ACK Collection is empty");
				break;
				
			case 15: // Create ORU_R01 Message and then Send
				objUserSession.sendMessage(getORU_R01());
				/*
				 * User can get Acknowledgment received from remote Server .This is demonstrated below.
				 * Acknowledgment message received  contains Acknowledgment for Event (ORU_R01) sent.
				 * This is how we receive Acknowledgment for event.
				 */
				Thread.sleep(6000);
				
				ISingleCollection<Message> ackCollectionForOserReporting = objUserSession.getRecievedMessagesCollection(strMsgControlID);
				if(ackCollectionForOserReporting != null)
				{
					for(Message objMessage :ackCollectionForOserReporting)
					{
						if(objMessage.getMessageStructure().equals(EnumMessageStructure.ACK.getValue()))
						{
							ACK ackMessage = (ACK)objMessage;
							System.out.println("ACK Received for event :: " + ackMessage.getTriggerEvent());
						}
						else
						{
							System.out.println("Response Received for event :: "+objMessage.getMessageCode()+"_" + objMessage.getTriggerEvent());
						}
					}
				}
				else
					System.out.println("ACK Collection is empty");
				break;

			case 16: // Create SLR_S28 Message and then Send
				objUserSession.sendMessage(getSLR_S28());
				/*
				 * User can get Acknowledgment received from remote Server .This is demonstrated below.
				 * Acknowledgment message received  contains Acknowledgment for Event (SLR_S28) sent.
				 * This is how we receive Acknowledgment for event.
				 */
				Thread.sleep(6000);
				
				ISingleCollection<Message> ackCollectionForMaterialsMgmnt = objUserSession.getRecievedMessagesCollection(strMsgControlID);
				if(ackCollectionForMaterialsMgmnt != null)
				{
					for(Message objMessage :ackCollectionForMaterialsMgmnt)
					{
						if(objMessage.getMessageStructure().equals(EnumMessageStructure.ACK.getValue()))
						{
							ACK ackMessage = (ACK)objMessage;
							System.out.println("ACK Received for event :: " + ackMessage.getTriggerEvent());
						}
						else
						{
							System.out.println("Response Received for event :: "+objMessage.getMessageCode()+"_" + objMessage.getTriggerEvent());
						}
					}
				}
				else
					System.out.println("ACK Collection is empty");
				break;

			case 17: // Create QBP_E03 Message and then Send
				objUserSession.sendMessage(getQBP_E03());
				//objUserSession.sendMessage(getEHC_E12());
				/*
				 * User can get Acknowledgment received from remote Server .This is demonstrated below.
				 * Acknowledgment message received  contains Acknowledgment for Event (QBP_E03) sent.
				 * This is how we receive Acknowledgment for event.
				 */
				Thread.sleep(6000);
				
				ISingleCollection<Message> ackCollectionForClaimsAndReimbursement = objUserSession.getRecievedMessagesCollection(strMsgControlID);
				if(ackCollectionForClaimsAndReimbursement != null)
				{
					for(Message objMessage :ackCollectionForClaimsAndReimbursement)
					{
						
							System.out.println("Response Received for event :: "+objMessage.getMessageCode()+"_" + objMessage.getTriggerEvent());
						
					}
				}
				else
					System.out.println("Response Collection is empty");
				break;
				
			default:
				break;
			}
		}
		catch (Exception e)
		{
			System.out.println("Error Ocured (Continue client) == > "+e.getMessage());
		}
	}
	/*
	 * This method populates ADT_A02 message.
	 */
	private ADT_A02 getADTA02()
	{
		/* 
		 * To create new Message ADTRecepient is required.
		 * 1)Initialize  ADTRecepient
		 * 2)Specify Trigger event & message structure of message to be created.
		 */
		strMsgControlID = "MSG010"+MsgControlID++;

		ADTRecepient objPatientAdminRecipient = new ADTRecepient();
		ADT_A02 objADT_A02 = (ADT_A02)objPatientAdminRecipient.createMessage(EnumMessageCode.ADT, EnumTriggerEvent.A02);

		//Populate MSH Segment
		MSH objMSH = objPopulateTest.populateMSH();
		objMSH.setMessageType("ADT","A02","ADT_A02");
		objMSH.setMessageControlID(strMsgControlID);
		objADT_A02.setHeader(objMSH);
		
		//Populate EVN Segment
		EVN objEVN = objPopulateTest.populateEVN();
		objADT_A02.setEventTypeSegment(objEVN);

		//Populate PID Segment
		PID objPID = objPopulateTest.populatePID();
		objADT_A02.setPatientIdentificationSegment(objPID);

		//Populate PV1 segment
		PV1 objPV1 = objPopulateTest.populatePV1();
		objADT_A02.setPatientVisitSegment(objPV1);

		return objADT_A02;
	}
	
	private ADT_A01 getADTA01()  
	{ 
		strMsgControlID = "MSG010"+MsgControlID++;

		ADTRecepient objPatientAdminRecipient = new ADTRecepient();
		ADT_A01 objADT_A01 = (ADT_A01)objPatientAdminRecipient.createMessage(EnumMessageCode.ADT, EnumTriggerEvent.A01);

		MSH objMSH = objPopulateTest.populateMSH();
		objMSH.setMessageType("ADT","A01","ADT_A01");
		objMSH.setMessageControlID(strMsgControlID);
		objADT_A01.setHeader(objMSH);

		//EVN Segment
		EVN objEVN = objPopulateTest.populateEVN();
		objADT_A01.setEventTypeSegment(objEVN);

		//PID segment
		PID objPID = objPopulateTest.populatePID();
		objADT_A01.setPatientIdentificationSegment(objPID);

		//PV1 Segment
		PV1 objPV1 = objPopulateTest.populatePV1();
		objADT_A01.setPatientVisitSegment(objPV1);
		
		return objADT_A01;

	}
	
	/*
	 * This method populates NMD_N02 message.
	 */
	private NMD_N02 getNMDN02()
	{
		AppMgtSource objAppMgtSource = new AppMgtSource();
		NMD_N02 objNMD_N02 = (NMD_N02)objAppMgtSource.createMessage(EnumMessageCode.NMD, EnumTriggerEvent.N02);
		
		strMsgControlID = "MSG010"+MsgControlID++;
		
		//Populate MSH Segment
		MSH objMSH = objPopulateTest.populateMSH();
		objMSH.setMessageType("NMD","N02","NMD_N02");
		objMSH.setMessageControlID(strMsgControlID);
		objNMD_N02.setHeader(objMSH);
				
		IMap objMessageMap = MessageMapReader.createInstance().getMessageMap(EnumMessageCode.NMD, EnumTriggerEvent.N02);
		
		IMap objClockAndStatsWithNotesGroupMap = objMessageMap.getGroupMap(EnumSegments.HL7_GROUP_CLOCK_AND_STATS_WITH_NOTES);

		IGroup objClockAndStatsWithNotesGroup = new Group(EnumSegments.HL7_GROUP_CLOCK_AND_STATS_WITH_NOTES, objClockAndStatsWithNotesGroupMap);
		
		objNMD_N02.addClockAndStatsWithNotesGroups(objClockAndStatsWithNotesGroup);
		return objNMD_N02;
	}
	
	/*
	 * This method populates BAR_P12 message.
	 */
	private BAR_P12 getBARP12()
	{
		FinancialRecepient objFinancialMgtRecepient = new FinancialRecepient();
		BAR_P12 objBAR_P12 = (BAR_P12)objFinancialMgtRecepient.createMessage(EnumMessageCode.BAR, EnumTriggerEvent.P12);
		
		strMsgControlID = "MSG010"+MsgControlID++;
		
		//Populate MSH Segment
		MSH objMSH = objPopulateTest.populateMSH();
		objMSH.setMessageType("BAR","P12","BAR_P12");
		objMSH.setMessageControlID(strMsgControlID);
		objBAR_P12.setHeader(objMSH);
		
		//Populate EVN Segment
		EVN objEVN = objPopulateTest.populateEVN();
		objBAR_P12.setEventTypeSegment(objEVN);

		//Populate PID Segment
		PID objPID = objPopulateTest.populatePID();
		objBAR_P12.setPatientIdentificationSegment(objPID);

		//Populate PV1 segment
		PV1 objPV1 = objPopulateTest.populatePV1();
		objBAR_P12.setPatientVisitSegment(objPV1);
		
		return objBAR_P12;
	}
	
	/*
	 * This method populates ESR_U02 message 
	 */
	private ESR_U02 getESR_U02()
	{
		ClinicalLabAutoRecepient objClinicalLabAutoRecepient = new ClinicalLabAutoRecepient();
		ESR_U02 objESR_U02 = (ESR_U02)objClinicalLabAutoRecepient.createMessage(EnumMessageCode.ESR, EnumTriggerEvent.U02);
		
		strMsgControlID = "MSG010"+MsgControlID++;
		
		//Populate MSH Segment
		MSH objMSH = objPopulateTest.populateMSH();
		objMSH.setMessageType("ESR","U02","ESR_U02");
		objMSH.setMessageControlID(strMsgControlID);
		objESR_U02.setHeader(objMSH);
		
		//Populate EQU Segment
		EQU objEQU = objPopulateTest.populateEQU();
		objESR_U02.setEquipmentDetailSegment(objEQU);
		
		return objESR_U02;
	}
	
	/*
	 * This method populates MFN_M13 message
	 */
	private MFN_M13 getMFN_M13()
	{
		MasterFileRecepient objMasterFileRecepient= new MasterFileRecepient();
		MFN_M13 objMFN_M13 = (MFN_M13)objMasterFileRecepient.createMessage(EnumMessageCode.MFN, EnumTriggerEvent.M13);
		
		strMsgControlID = "MSG010"+MsgControlID++;
		
		//Populate MSH Segment
		MSH objMSH = objPopulateTest.populateMSH();
		objMSH.setMessageType("MFN","M13","MFN_M13");
		objMSH.setMessageControlID(strMsgControlID);
		objMFN_M13.setHeader(objMSH);
		
		//Popualte MFI segment
		MFI objMFI = objPopulateTest.populateMFI();
		objMFN_M13.setMasterFileIdentificationSegment(objMFI);
		
		//Populate MFE Segment
		MFE objMFE = objPopulateTest.populateMFE();
		objMFN_M13.addMasterFileEntrySegment(objMFE);
		
		return objMFN_M13;
	}
	
	/*
	 * This method populates MDM_T01 message
	 */
	private MDM_T01 getMDM_T01()
	{
		strMsgControlID = "MSG010"+MsgControlID++;
		MediRecRecepient objMediRecRecepient = new MediRecRecepient();
		MDM_T01 objMDM_T01 = (MDM_T01)objMediRecRecepient.createMessage(EnumMessageCode.MDM, EnumTriggerEvent.T01);
		
		//Populate MSH Segment
		MSH objMSH = objPopulateTest.populateMSH();
		objMSH.setMessageType("MDM","T01","MDM_T01");
		objMSH.setMessageControlID(strMsgControlID);
		objMDM_T01.setHeader(objMSH);
		
		//Populate EVN Segment
		EVN objEVN = objPopulateTest.populateEVN();
		objMDM_T01.setEventTypeSegment(objEVN);

		//Populate PID Segment
		PID objPID = objPopulateTest.populatePID();
		objMDM_T01.setPatientIdentificationSegment(objPID);

		//Populate PV1 segment
		PV1 objPV1 = objPopulateTest.populatePV1();
		objMDM_T01.setPatientVisitSegment(objPV1);
		
		//Populate TXA segment
		TXA objTXA=objPopulateTest.populateTXA();
		objMDM_T01.setDocumentNotificationSegment(objTXA);
		
		return objMDM_T01;
		
	}
	
	/*
	 * This method populates OMG_O19 message
	 */
	
	private OMG_O19 getOMG_O19()
	{
		strMsgControlID = "MSG010"+MsgControlID++;
		OrderEntryRecepient objOrderEntryRecepient = new OrderEntryRecepient();
		OMG_O19 objOMG_O19 = (OMG_O19)objOrderEntryRecepient.createMessage(EnumMessageCode.OMG, EnumTriggerEvent.O19);
		
		//Populate MSH Segment
		MSH objMSH = objPopulateTest.populateMSH();
		objMSH.setMessageType("OMG","O19","OMG_O19");
		objMSH.setMessageControlID(strMsgControlID);
		objOMG_O19.setHeader(objMSH);
		
		//Populate Order group
		IMap objMessageMap = MessageMapReader.createInstance().getMessageMap(EnumMessageCode.OMG, EnumTriggerEvent.O19);
		
		IMap objOrderGroupMap = objMessageMap.getGroupMap(EnumSegments.HL7_GROUP_ORDER);

		IGroup objOrderGroup = new Group(EnumSegments.HL7_GROUP_ORDER, objOrderGroupMap);
		
		ORC objORC = objPopulateTest.populateORC();
		objOrderGroup.addSegment(EnumSegments.HL7_SEG_ORC, objORC);
		
		OBR objOBR = objPopulateTest.populateOBR();
		objOrderGroup.addSegment(EnumSegments.HL7_SEG_OBR, objOBR);
		
		objOMG_O19.addOrderGroup(objOrderGroup);
		
		return objOMG_O19;
	}
	
	/*
	 * This method populates PGL_PC6 message.
	 */
	private PGL_PC6 getPGL_R30()
	{
		strMsgControlID = "MSG010"+MsgControlID++;
		PatientCareRecepient objpatiCareRecepient = new PatientCareRecepient();
		PGL_PC6 objPGL_PC6 = (PGL_PC6)objpatiCareRecepient.createMessage(EnumMessageCode.PGL, EnumTriggerEvent.PC6);
		
		//Populate MSH Segment
		MSH objMSH = objPopulateTest.populateMSH();
		objMSH.setMessageType("PGL","PC6","PGL_PC6");
		objMSH.setMessageControlID(strMsgControlID);
		objPGL_PC6.setHeader(objMSH);
		
		//Populate PID Segment
		PID objPID = objPopulateTest.populatePID();
		objPGL_PC6.setPatientIdentificationSegment(objPID);
		
		IMap objMessageMap = MessageMapReader.createInstance().getMessageMap(EnumMessageCode.PGL, EnumTriggerEvent.PC6);
		
		IMap objGoalGroupMap = objMessageMap.getGroupMap(EnumSegments.HL7_GROUP_GOAL);

		IGroup objGoalGroup = new Group(EnumSegments.HL7_GROUP_GOAL, objGoalGroupMap);
		
		GOL objGOL = objPopulateTest.populateGOL();
		objGoalGroup.addSegment(EnumSegments.HL7_SEG_GOL, objGOL);
		
		objPGL_PC6.addGoalGroup(objGoalGroup);
		
		return objPGL_PC6;
	}
	
	/*
	 * This method populates PMU_B01 message.
	 */
	private PMU_B01 getPMU_B01()
	{
		strMsgControlID = "MSG010"+MsgControlID++;
		PersonalMgmtRecepient objperMgmtRecepient = new PersonalMgmtRecepient();
		PMU_B01 objPMU_B01 = (PMU_B01)objperMgmtRecepient.createMessage(EnumMessageCode.PMU, EnumTriggerEvent.B01);
		
		//Populate MSH Segment
		MSH objMSH = objPopulateTest.populateMSH();
		objMSH.setMessageType("PMU","B01","PMU_B01");
		objMSH.setMessageControlID(strMsgControlID);
		objPMU_B01.setHeader(objMSH);
		
		//Populate EVN segment
		EVN objEVN = objPopulateTest.populateEVN();
		objPMU_B01.setEventTypeSegment(objEVN);
		
		//Populate STF segment
		STF objSTF = objPopulateTest.populateSTF();
		objPMU_B01.setStaffSegment(objSTF);
		
		return objPMU_B01;
	}
	
	/*
	 * This method populates SRM_S01 message
	 */
	private SRM_S01 getSRM_S01()
	{
		strMsgControlID = "MSG010"+MsgControlID++;
		SchedulingRecepient objSchedulingRecepient = new SchedulingRecepient();
		SRM_S01 objSRM_S01 = (SRM_S01)objSchedulingRecepient.createMessage(EnumMessageCode.SRM, EnumTriggerEvent.S01);
		
		//Populate MSH Segment
		MSH objMSH = objPopulateTest.populateMSH();
		objMSH.setMessageType("SRM","S01","SRM_S01");
		objMSH.setMessageControlID(strMsgControlID);
		objSRM_S01.setHeader(objMSH);
		
		//Populate ARQ segment.
		ARQ objARQ = objPopulateTest.populateARQ();
		objSRM_S01.setAppointmentRequestSegment(objARQ);
		
		IMap objMessageMap = MessageMapReader.createInstance().getMessageMap(EnumMessageCode.SRM, EnumTriggerEvent.S01);
		
		IMap objResourcesGroupMap = objMessageMap.getGroupMap(EnumSegments.HL7_GROUP_RESOURCES);

		IGroup objResourcesGroup = new Group(EnumSegments.HL7_GROUP_RESOURCES, objResourcesGroupMap);
		
		RGS objRGS = objPopulateTest.populateRGS();
		objResourcesGroup.addSegment(EnumSegments.HL7_SEG_RGS, objRGS);
		
		objSRM_S01.addResourcesGroup(objResourcesGroup);
		
		return objSRM_S01;
		
	}
	
	/*
	 * This method populates RQI_I01 message.
	 */
	private RQI_I01 getRQI_I01()
	{
		strMsgControlID = "MSG010"+MsgControlID++;
		PatientRefRecepient objPatientRefRecepient = new PatientRefRecepient();
		RQI_I01 objRQI_I01 = (RQI_I01)objPatientRefRecepient.createMessage(EnumMessageCode.RQI, EnumTriggerEvent.I01);
		
		//Populate MSH Segment
		MSH objMSH = objPopulateTest.populateMSH();
		objMSH.setMessageType("RQI","I01","RQI_I01");
		objMSH.setMessageControlID(strMsgControlID);
		objRQI_I01.setHeader(objMSH);
		
		IMap objMessageMap = MessageMapReader.createInstance().getMessageMap(EnumMessageCode.RQI, EnumTriggerEvent.I01);
		
		IMap objProviderGroupMap = objMessageMap.getGroupMap(EnumSegments.HL7_GROUP_PROVIDER);

		IGroup objProviderGroup = new Group(EnumSegments.HL7_GROUP_PROVIDER, objProviderGroupMap);
		
		PRD objPRD = objPopulateTest.populatePRD();
		objProviderGroup.addSegment(EnumSegments.HL7_SEG_PRD, objPRD);
		
		objRQI_I01.addProviderGroup(objProviderGroup);
		
		//Populate PID Segment
		PID objPID = objPopulateTest.populatePID();
		objRQI_I01.setPatientIdentificationSegment(objPID);
		
		return objRQI_I01;
	}
	/*
	 * This method populates ORU_R01 message.
	 */
	private ORU_R01 getORU_R01()
	{
		strMsgControlID = "MSG010"+MsgControlID++;
		ObsvRepRecepient objObsvRepRecepient = new ObsvRepRecepient();
		ORU_R01 objORU_R01 = (ORU_R01)objObsvRepRecepient.createMessage(EnumMessageCode.ORU, EnumTriggerEvent.R01);
		
		//Populate MSH Segment
		MSH objMSH = objPopulateTest.populateMSH();
		objMSH.setMessageType("ORU","R01","ORU_R01");
		objMSH.setMessageControlID(strMsgControlID);
		objORU_R01.setHeader(objMSH);
		
		IMap objMessageMap = MessageMapReader.createInstance().getMessageMap(EnumMessageCode.ORU, EnumTriggerEvent.R01);
		
		IMap objPatientResultGroupMap = objMessageMap.getGroupMap(EnumSegments.HL7_GROUP_PATIENT_RESULT);

		IGroup objPatientResultGroup = new Group(EnumSegments.HL7_GROUP_PATIENT_RESULT, objPatientResultGroupMap);
		
		IMap objOrderObservationGroupMap = objMessageMap.getGroupMap(EnumSegments.HL7_GROUP_ORDER_OBSERVATION);
		IGroup objOrderObservationGroup = new Group(EnumSegments.HL7_GROUP_ORDER_OBSERVATION, objOrderObservationGroupMap);
		
		OBR objOBR = objPopulateTest.populateOBR();
		objOrderObservationGroup.addSegment(EnumSegments.HL7_SEG_OBR, objOBR);
		
		objPatientResultGroup.addGroup(EnumSegments.HL7_GROUP_ORDER_OBSERVATION, objOrderObservationGroup);
		
		objORU_R01.addPatientResultGroup(objPatientResultGroup);
		
		return objORU_R01;
	}
	
	/*
	 * This method populates SLR_S28 Message.
	 */
	private SLR_S28 getSLR_S28()
	{
		strMsgControlID = "MSG010"+MsgControlID++;
		MaterialsMgtRecepient objMaterialsMgtRecepient = new MaterialsMgtRecepient();
		SLR_S28 objSLR_S28 = (SLR_S28)objMaterialsMgtRecepient.createMessage(EnumMessageCode.SLR, EnumTriggerEvent.S28);
		
		//Populate MSH Segment
		MSH objMSH = objPopulateTest.populateMSH();
		objMSH.setMessageType("SLR","S28","SLR_S28");
		objMSH.setMessageControlID(strMsgControlID);
		objSLR_S28.setHeader(objMSH);
		
		//Populate SLT Segment
		SLT objSLT = objPopulateTest.populateSLT();
		objSLR_S28.addSterilizationLotSegment(objSLT);
		
		return objSLR_S28;
		
	}
	
	/*
	 * This method populates QBP_E03 message.
	 */
	private QBP_E03 getQBP_E03()
	{
		
		strMsgControlID = "MSG010"+MsgControlID++;
		ClaimsAndReimbursementSource objClaimsAndReimbursementSource = new ClaimsAndReimbursementSource();
		QBP_E03 objQBP_E03 = (QBP_E03)objClaimsAndReimbursementSource.createMessage(EnumMessageCode.QBP, EnumTriggerEvent.E03);
		
		//Populate MSH Segment
		MSH objMSH = objPopulateTest.populateMSH();
		objMSH.setMessageType("QBP","E03","QBP_E03");
		objMSH.setMessageControlID(strMsgControlID);
		objQBP_E03.setHeader(objMSH);
		
		IMap objMessageMap = MessageMapReader.createInstance().getMessageMap(EnumMessageCode.QBP, EnumTriggerEvent.E03);
		
		IMap objQueryInformationGroupMap = objMessageMap.getGroupMap(EnumSegments.HL7_GROUP_QUERY_INFORMATION);

		IGroup objQueryInformationGroup = new Group(EnumSegments.HL7_GROUP_QUERY_INFORMATION, objQueryInformationGroupMap);
		
		//Populate QPD segment
		QPD objQPD = objPopulateTest.populateQPD();
		objQueryInformationGroup.addSegment(EnumSegments.HL7_SEG_QPD, objQPD);
		
		//Populate RCP segment
		RCP objRCP = objPopulateTest.populateRCP();
		objQueryInformationGroup.addSegment(EnumSegments.HL7_SEG_RCP, objRCP);
		
		objQBP_E03.addQueryInformationGroup(objQueryInformationGroup);

		return objQBP_E03;
		
	}
	
	/*
	 * This method populates EHC_E12 message.
	 */
	private EHC_E12 getEHC_E12()
	{
		strMsgControlID = "MSG010"+MsgControlID++;
		
		ClaimsAndReimbursementSource objClaimsAndReimbursementScource= new ClaimsAndReimbursementSource();
		EHC_E12 objEHC_E12 = (EHC_E12)objClaimsAndReimbursementScource.createMessage(EnumMessageCode.EHC, EnumTriggerEvent.E12);
		
		//Populate MSH Segment
		MSH objMSH = objPopulateTest.populateMSH();
		objMSH.setMessageType("EHC","E12","EHC_E12");
		objMSH.setMessageControlID(strMsgControlID);
		objEHC_E12.setHeader(objMSH);
		
		//Populate RFI Segment
		RFI objRFI = objPopulateTest.populateRFI();
		objEHC_E12.setRequestForInformationSegment(objRFI);
		
		//Populate IVC Segment
		IVC objIVC = objPopulateTest.populateIVC();
		objEHC_E12.setInVoiceSegment(objIVC);
		
		//Populate PSS Segment 
		PSS objPSS = objPopulateTest.populatePSS();
		objEHC_E12.setProductOrServiceSectionSegment(objPSS);
		
		//Populate PSG Segment
		PSG objPSG = objPopulateTest.populatePSG();
		objEHC_E12.setProductOrServiceGroupSegment(objPSG);
		
		IMap objMessageMap = MessageMapReader.createInstance().getMessageMap(EnumMessageCode.EHC, EnumTriggerEvent.E12);
		
		IMap objRequestGroupMap = objMessageMap.getGroupMap(EnumSegments.HL7_GROUP_REQUEST);

		IGroup objRequestGroup = new Group(EnumSegments.HL7_GROUP_REQUEST, objRequestGroupMap);
		
		//Populate OBR segment
		OBR objOBR = objPopulateTest.populateOBR();
		objRequestGroup.addSegment(EnumSegments.HL7_SEG_OBR, objOBR);
		
		objEHC_E12.addRequestGroup(objRequestGroup);
		
		return objEHC_E12;
		
	}
	
	
	/*
	 * This method populates QBP_Q21 message
	 */
	private QBP_Q21 getQBPQ21(String priority)
	{
		strMsgControlID = "MSG010"+MsgControlID++;
		
		ADTSource objQBP_Q21Source= new ADTSource();
		QBP_Q21 objQBP_Q21 = (QBP_Q21)objQBP_Q21Source.createMessage(EnumMessageCode.QBP, EnumTriggerEvent.Q21);
		
		//Populate MSH Segment
		MSH objMSH = objPopulateTest.populateMSH();
		objMSH.setMessageType("QBP","Q21","QBP_Q21");
		objMSH.setMessageControlID(strMsgControlID);
		objQBP_Q21.setHeader(objMSH);
		
		//Populate QPD Segment
		QPD objQPD = objPopulateTest.populateQPD();
		objQBP_Q21.setQueryParameterDefinitionSegment(objQPD);
		
		//Populate RCP Segment
		RCP objRCP = objPopulateTest.populateRCP();
		objRCP.setQueryPriority(priority);
		objQBP_Q21.setResponseControlParametersSegment(objRCP);
		
		return objQBP_Q21;
		
	}

	/*
	 * This method creates Batch file containing batch of ADT_A02 and QRY_A19 message.
	 */
	private IHL7BatchFile getADT_QRY_A19BatchFile()
	{
		FHS objBatchFileHeader  = new FHS();
		objBatchFileHeader.setFieldSeparator('|');
		objBatchFileHeader.setEncodingChars('^','&','~','\\','#');
		objBatchFileHeader.setFileControlID("File565");

		ISingleCollection<IHL7Batch> objIHL7BatchCollection = new SingleCollection<IHL7Batch>();
		objIHL7BatchCollection.add(getADT_QRYEventBatch());

		FTS objBatchFileTrailer = new FTS();
		objBatchFileTrailer.setFileBatchCount("1");

		IHL7BatchFile objBatchFile = new HL7BatchFile(objBatchFileHeader,objBatchFileTrailer,objIHL7BatchCollection);

		return objBatchFile;
	}
	/*
	 * This method populates Batch containing ADT_A02 and QRY_A19 message.
	 */
	private IHL7Batch getADT_QRYEventBatch()
	{

		BHS objBatchHeader  = new BHS();
		objBatchHeader.setBatchFieldSeparator('|');
		objBatchHeader.setBatchEncodingChars('^','&','~','\\','#');
		objBatchHeader.setBatchControlID("Batch56545");

		ISingleCollection<Message> objMessageCollection = new SingleCollection<Message>();
		objMessageCollection.add(getADTA02());

		BTS objBatchTrailer = new BTS();
		objBatchTrailer.addBatchTotals("2");

		IHL7Batch objBatch = new HL7Batch(objBatchHeader,objBatchTrailer,objMessageCollection);

		return objBatch;
	}
	
	/**
	 * This method is invoked when exception is fetched from remote end.
	 * @ex Exception fetched
	 * @buffer for which exception is received
	 */
	public void onException(Exception ex, byte[] buffer) 
	{
		System.out.println("In On Exception Receiced : Printing Stacktrace...");
		System.out.println(ex.getMessage());
		System.out.println("End of Stacktrace....");
		try
		{
			System.out.println("Byte Buffer is : ");
			ByteArrayOutputStream objByteArrayOutputStream = new ByteArrayOutputStream();
			objByteArrayOutputStream.write(buffer);

			objByteArrayOutputStream.writeTo(System.out);
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
	}

	/**
	 * This method is invoked when exception is fetched from remote end.
	 * @ex Exception fetched
	 * @objISegmentSet for which Segment Set is Received.
	 */
	public void onException(Exception ex, ISegmentSet objISegmentSet)
	{
		System.out.println("In On Exception Receiced : Printing Stacktrace...");
		System.out.println(ex.getMessage());
		System.out.println("End of Stacktrace....");
		try
		{
			System.out.println("Segment Set is : ");
			ISingleCollection<ISegment> objISegmentSetCollection = objISegmentSet.getList();
			if(objISegmentSetCollection!=null)
			{
				System.out.println("Received Segment Set Contains following Segments:");
				for(ISegment objISegment : objISegmentSetCollection)
				{
					System.out.println(objISegment.getName());
				}
			}
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
	}

	/**
	 * This method is invoked when deferred response is received.
	 */
	public void onResponseReceive(Message deferredResponse) 
	{
		System.out.println("Deferred Response Received............ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");

		String strFilePath = null;
		try
		{
			strFilePath = "E:\\Server" + i++ + ".hl7"; //reader.readLine();

			HL7Serializer objHL7Serializer = new HL7Serializer();
			objHL7Serializer.serialize(deferredResponse.getSegmentSet(), strFilePath);

			System.out.print("Message serialized successfully\n");

			//After receiving deferredResponse user sends Acknowledgment in response to Deferred response.
			//generate Acknowledgment with respect to deferred response.
			ACK ackMessage = generateAcknowledgement(deferredResponse);

			//Send Acknowledgment for deferred response
			objUserSession.sendMessage(ackMessage);

			synchronized (this) 
			{
				notify();	
			}
		}catch(IOException ioe)
		{
			ioe.printStackTrace();
		}
		catch (InvalidMessageException e) 
		{
			e.printStackTrace();
		} 
	}

	/**
	 * This method is invoked when deferred response received is in Batch.
	 */
	public void onBatchReceive(IHL7BatchFile objBatchFile) 
	{
		ISingleCollection<IHL7Batch> objBatchCollection = objBatchFile.getHL7BatchCollection();
		for(IHL7Batch objBatch : objBatchCollection)
		{
			if(objBatch.isResponseBatch()  && objBatch.isDeferred())
			{
				acknowledgeResponseBatch(objBatch);
			}
			else
				System.out.println("ACK received for BatchID  " + objBatch.getBatchControlID());
		}
	}

	//This will generate the Batch which will acknowledge the Response received. 
	private void acknowledgeResponseBatch(IHL7Batch objHL7Batch)
	{
		System.out.println("Deferred Response Received is Batch............ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
		try 
		{

			//After receiving deferredResponse user sends Acknowledgment in response to Deferred response.
			//generate Acknowledgment with respect to deferred response.

			BHS objBatchHeader  = new BHS();
			objBatchHeader.setBatchFieldSeparator('|');
			objBatchHeader.setBatchEncodingChars('^','&','~','\\','#');
			objBatchHeader.setBatchControlID(objHL7Batch.getBatchControlID());//Generate it using UUID jar.

			ISingleCollection<Message> objMessageCollection = generateAcknowledgement(objHL7Batch.getMessageCollection());

			int iMessageCount = 0;
			if(objMessageCollection != null )
				iMessageCount = objMessageCollection.size();

			BTS objBatchTrailer = new BTS();
			objBatchTrailer.addBatchTotals(""+iMessageCount);

			IHL7Batch objBatch = new HL7Batch(objBatchHeader,objBatchTrailer,objMessageCollection);

			ISingleCollection<IHL7Batch> objIHL7BatchCollection = new SingleCollection<IHL7Batch>();
			objIHL7BatchCollection.add(objBatch);

			FHS objBatchFileHeader  = new FHS();
			objBatchFileHeader.setFieldSeparator('|');
			objBatchFileHeader.setEncodingChars('^','&','~','\\','#');
			objBatchFileHeader.setFileControlID(StandardMethods.generateUUID());

			FTS objBatchFileTrailer = new FTS();
			objBatchFileTrailer.setFileBatchCount("1");

			IHL7BatchFile objBatchFile = new HL7BatchFile(objBatchFileHeader,objBatchFileTrailer,objIHL7BatchCollection);

			//Send Acknowledgment for deferred response
			System.out.println("Sending ACK for Deferred Response Batch..");

			objUserSession.sendBatchFile(objBatchFile);

			System.out.println("ACK for Deferred Response Batch is Sent ..");
			synchronized (this) 
			{
				notify();	
			}
		}
		catch (InvalidMessageException e) 
		{
			e.printStackTrace();
		}
		catch (IOException e) 
		{
			e.printStackTrace();
		}
	}
	/**
	 * This method simulates user action to generate Acknowledgment from message received in the batch.
	 * This method is demonstrated for test purpose only.
	 * In the actual scenario,it is the responsibility of user to generates acknowledgment & sends it on remote end. 
	 * @param objMessageCollection specified Message collection from 
	 * @return objACKCollection - collection of ACK messages.
	 */
	public ISingleCollection<Message> generateAcknowledgement(ISingleCollection<Message> objMessageCollection)
	{
		ISingleCollection<Message> objACKCollection = new SingleCollection<Message>();
		for(Message objMessage :objMessageCollection)
		{
			objACKCollection.add(generateAcknowledgement(objMessage));
		}
		return objACKCollection;
	}
	/**
	 * This method simulates user action to generate Acknowledgment from message received.
	 * This method is demonstrated for test purpose only.
	 * In the actual scenario,it is the responsibility of user to generates acknowledgment & sends it on remote end. 
	 * @param objReceivedMessage specified Message object
	 * @return ACK message object
	 */
	public ACK generateAcknowledgement(Message objReceivedMessage)
	{
		strMsgControlID = "MSG58"+MsgControlID++;
		
		IMessageMapReader objMessageMapReader = MessageMapReader.createInstance();
		IMap objMessageMap = objMessageMapReader.getMessageMap(EnumMessageCode.ACK, null);

		ACK ackMessage = new ACK(StandardMethods.getEnumTriggerEvent(objReceivedMessage.getTriggerEvent()), objMessageMap);
		MSH objMSH = objPopulateTest.populateMSH();
		objMSH.setMessageType(EnumMessageCode.ACK.getValue(), objReceivedMessage.getTriggerEvent(),EnumMessageStructure.ACK.getValue());
		objMSH.setMessageControlID(strMsgControlID);
		ackMessage.setHeader(objMSH);
		
		//MSA Segment
		MSA objMSA = new MSA();
		objMSA.setAcknowledgmentCode("AA");
		objMSA.setMessageControlID(objReceivedMessage.getHeader().getMessageControlID().getValue().toString());
		objMSA.setExpectedSequenceNumber("1234567");
		ackMessage.setMessageAcknowledgmentSegment(objMSA);
		return ackMessage;
	}
	/*
	 * This will create Separate Server Session for the HL7System.  
	 */
	private void createServerSesssion()
	{
		//instantiating Server Session thread which will be continuously listening on specific ip and port.
		MyServerSession objMyServerSession = new MyServerSession();
		objMyServerSession.start();
	}
	/**
	 * This class internally creates the User Session for sending Query and receiving responses.   
	 */
	public class MyServerSession extends Thread implements IProcessHandler  
	{
		String strMsgControlID =null;
		private int messageControlId = 0,i=0;
		UserSession objUserSession =null;
		MessageFactory objMessageFactory =null;
		String strMessageControlid =null;
		ITransactionHandler objServerTransactionHandler =null;


		public void run() 
		{
			initiateServerSession();
		}
		public void initiateServerSession()
		{
			try 
			{
				//Creating Server Session for HL7System.
				ServerSession objServerSession = new ServerSession();

				//Create MessageFactory to provide support for creation and population of messages.
				objMessageFactory = MessageFactory.createInstance();


				/*   Patient Administration System */
				/*
				 * Instantiating Message Recipient for HL7System
				 * User can provide his own implementation of Message Recipient by implementing IMessageReceipient interface. 
				 */
				IMessageRecepient objADTRecepient = new ADTRecepient();

				/*
				 * Adding Patient Admin Recipient on Message Factory.
				 * By setting this recipient client becomes capable to create messages and send Events of Patient Admin System
				 * Similarly user can set recipients for different systems.
				 * sdk for HL7 provides sources for all systems specified by HL7.
				 */ 
				objMessageFactory.addMessageRecepient(objADTRecepient);

				/*
				 * Instantiating Message Source for HL7System
				 * User can provide his own implementation of Message Source by implementing IMessageSource interface. 
				 */
				IMessageSource objADTSource  = new ADTSource();

				/*
				 * Adding Patient Admin Source and Recipient on on Message Factory.
				 * By setting this source client becomes capable to create messages and receive responses of Patient Admin System
				 * Similarly user can set sources for different systems.
				 * sdk for HL7 provides sources for all systems specified by HL7.
				 */ 
				objMessageFactory.addMessageSource(objADTSource);


				/*   Query System */
				//Initiating Message Recipient for Query System.
				IMessageRecepient objQryRecepient = new QryRecepient();

				//Add the Message Recipient in MessageFactory.
				objMessageFactory.addMessageRecepient(objQryRecepient);

				//Initiating Message Source for Query System.
				IMessageSource objQrySource  = new QrySource();

				//Add MessageRecipient to MessageFactory.
				objMessageFactory.addMessageSource(objQrySource);

				
				  //  Application management System 
				//Initiating Message Recipient for Application management System.
				IMessageRecepient objAppMgtRecepient = new AppMgtRecepient();

				//Add the Message Recipient in MessageFactory.
				objMessageFactory.addMessageRecepient(objAppMgtRecepient);

				//Initiating Message Source for Application management System.
				IMessageSource objAppMgtSource  = new AppMgtSource();

				//Add MessageRecipient to MessageFactory.
				objMessageFactory.addMessageSource(objAppMgtSource);


				 //  Clinical Laboratory Automation System 
				//Initiating Message Recipient for Clinical Laboratory Automation System.
				IMessageRecepient objClinicalLabAutoRecepient = new ClinicalLabAutoRecepient();

				//Add the Message Recipient in MessageFactory.
				objMessageFactory.addMessageRecepient(objClinicalLabAutoRecepient);

				//Initiating Message Source for Clinical Laboratory Automation System.
				IMessageSource objClinicalLabAutoSource  = new ClinicalLabAutoSource();

				//Add MessageRecipient to MessageFactory.
				objMessageFactory.addMessageSource(objClinicalLabAutoSource);


				 //  Financial Management System 
				//Initiating Message Recipient for Financial Management System.
				IMessageRecepient objFinancialRecepient = new FinancialRecepient();

				//Add the Message Recipient in MessageFactory.
				objMessageFactory.addMessageRecepient(objFinancialRecepient);

				//Initiating Message Source for Financial Management System.
				IMessageSource objFinancialSource  = new FinancialSource();

				//Add MessageRecipient to MessageFactory.
				objMessageFactory.addMessageSource(objFinancialSource);


				 //  Master Files System 
				//Initiating Message Recipient for Master Files System.
				IMessageRecepient objMasterFileRecepient = new MasterFileRecepient();

				//Add the Message Recipient in MessageFactory.
				objMessageFactory.addMessageRecepient(objMasterFileRecepient);

				//Initiating Message Source for Master Files System.
				IMessageSource objMasterFileSource  = new MasterFileSource();

				//Add MessageRecipient to MessageFactory.
				objMessageFactory.addMessageSource(objMasterFileSource);


				 //  Medical Records System 
				//Initiating Message Recipient for Medical Records System.
				IMessageRecepient objMediRecRecepient = new MediRecRecepient();

				//Add the Message Recipient in MessageFactory.
				objMessageFactory.addMessageRecepient(objMediRecRecepient);

				//Initiating Message Source for Medical Records System.
				IMessageSource objMediRecSource  = new MediRecSource();

				//Add MessageRecipient to MessageFactory.
				objMessageFactory.addMessageSource(objMediRecSource);


				 // Observation Reporting System 
				//Initiating Message Recipient for Observation Reporting System.
				IMessageRecepient objObsvRepRecepient = new ObsvRepRecepient();

				//Add the Message Recipient in MessageFactory.
				objMessageFactory.addMessageRecepient(objObsvRepRecepient);

				//Initiating Message Source for Observation Reporting System.
				IMessageSource objObsvRepSource  = new ObsvRepSource();

				//Add MessageRecipient to MessageFactory.
				objMessageFactory.addMessageSource(objObsvRepSource);


				 // Order Entry System 
				//Initiating Message Recipient for Order Entry System.
				IMessageRecepient objOrderEntryRecepient = new OrderEntryRecepient();

				//Add the Message Recipient in MessageFactory.
				objMessageFactory.addMessageRecepient(objOrderEntryRecepient);

				//Initiating Message Source for Order Entry System.
				IMessageSource objOrderEntrySource  = new OrderEntrySource();

				//Add MessageRecipient to MessageFactory.
				objMessageFactory.addMessageSource(objOrderEntrySource);


				//  Patient Care System 
				//Initiating Message Recipient for Patient Care System.
				IMessageRecepient objPatientCareRecepient = new PatientCareRecepient();

				//Add the Message Recipient in MessageFactory.
				objMessageFactory.addMessageRecepient(objPatientCareRecepient);

				//Initiating Message Source for Patient Care System.
				IMessageSource objPatientCareSource  = new PatientCareSource();

				//Add MessageRecipient to MessageFactory.
				objMessageFactory.addMessageSource(objPatientCareSource);


				//  Patient Referral System 
				//Initiating Message Recipient for Patient Referral System.
				IMessageRecepient objPatientRefRecepient = new PatientRefRecepient();

				//Add the Message Recipient in MessageFactory.
				objMessageFactory.addMessageRecepient(objPatientRefRecepient);

				//Initiating Message Source for Patient Referral System.
				IMessageSource objPatientRefSource  = new PatientRefSource();

				//Add MessageRecipient to MessageFactory.
				objMessageFactory.addMessageSource(objPatientRefSource);


				//  Personnel Management System 
				//Initiating Message Recipient for Personnel Management System.
				IMessageRecepient objPersonalMgmtRecepient = new PersonalMgmtRecepient();

				//Add the Message Recipient in MessageFactory.
				objMessageFactory.addMessageRecepient(objPersonalMgmtRecepient);

				//Initiating Message Source for Personnel Management System.
				IMessageSource objPersonalMgmtSource  = new PersonalMgmtSource();

				//Add MessageRecipient to MessageFactory.
				objMessageFactory.addMessageSource(objPersonalMgmtSource);


				 // Scheduling System 
				//Initiating Message Recipient for Scheduling System.
				IMessageRecepient objSchedulingRecepient = new SchedulingRecepient();

				//Add the Message Recipient in MessageFactory.
				objMessageFactory.addMessageRecepient(objSchedulingRecepient);

				//Initiating Message Source for Scheduling System.
				IMessageSource objSchedulingSource  = new SchedulingSource();

				//Add MessageRecipient to MessageFactory.
				objMessageFactory.addMessageSource(objSchedulingSource);

				
				//Claims And Reimbursement
				//Initiating Message Recipient for Claims And Reimbursement System.
				IMessageRecepient objClaimsAndReimbursementRecepient = new ClaimsAndReimbursementRecepient();
				
				//Add the Message Recipient in MessageFactory.
				objMessageFactory.addMessageRecepient(objClaimsAndReimbursementRecepient);
				
				//Initiating Message Source for Claims And Reimbursement System.
				IMessageSource objClaimsAndReimbursementSource = new ClaimsAndReimbursementSource();
				
				//Add the Message Source in MessageFactory.
				objMessageFactory.addMessageSource(objClaimsAndReimbursementSource);

				/*
				 * Instantiating IFragmentProcessor which handles the fragmentation and defragmention for larger messages.
				 * FragmentAgent is the default implementation provided by sdk for HL7.
				 * User can provide his own implementation for FragmentProcessor by implementing IFragmentProcessor interface.
				 */ 
				IFragmentProcessor objIFragmentProcessor = new FragmentAgent();

				//Setting Fragment processor on server session.
				objServerSession.setFragmentProcessor(objIFragmentProcessor);

				/*
				 * Instantiating IBatchProcessor which handles HL7Batch and HL7BatchFiles.
				 * BatchAgent is the default implementation provided by SDK for HL7.
				 * User can provide his own implementation for BatchProcessor by implementing IBatchProcessor interface.
				 */
				IBatchProcessor objIBatchProcessor = new BatchAgent();

				//Setting Batch Processor on user session
				objServerSession.setBatchProcessor(objIBatchProcessor);
				
				/*
				 * Setting this class as ProcessHandler for HL7System.
				 * IProcessHandler interface must be implemented ,so that server can receive messages from client side. 
				 */
				objServerSession.setIProcessHandler(this);	

				//Set the reading and writing max length for this client which will be used to decide whehther to fragment or not.
				objServerSession.setReadWriteLength(1024,1024);

				//Setting time period for which ClientSession will read on socket 
				//for given time period in milliseconds. 
				//The timeout must be > 0. A timeout of zero is interpreted as an infinite timeout. 
				objServerSession.setTimeOut(0);

				//Reading IP address for HL7System.
				System.out.print("Enter Ip address for HL7System server is started : ");
				InputStreamReader input = new InputStreamReader(System.in);
				BufferedReader reader = new BufferedReader(input);
				String strIp = reader.readLine();

				//Reading port for HL7System.
				System.out.print("Enter Port for HL7System server is Listening : ");
				String strPort = reader.readLine();
				int iPort = Integer.parseInt(strPort);

				/*
				 * Starts the ServerSession for HL7System Server on given IP and port.
				 */
				objServerSession.start(strIp, iPort);

			}
			catch (Exception e)
			{
				System.out.println("Error Ocured (Ending Client..)== > "+e.getMessage());
				e.printStackTrace();
			}
		}
		
		/**
		 * This method is implementation of IProcesshandler interface.
		 * This method is invoked when SDK receives file containing batch of HL7 messages from remote system.
		 * @param objClientSession session of remote end
		 */
		public void OnBatchFileReceive(ClientSession objClientSession) throws InvalidMessageException
		{
			try
			{
				IHL7BatchFile objHL7BatchFile = objClientSession.getBatchFile();
				for(IHL7Batch objHL7Batch : objHL7BatchFile.getHL7BatchCollection())
				{
					ISingleCollection<Message> objMessageCollection = objHL7Batch.getMessageCollection();
					ISingleCollection<Message> objAckCollection = new SingleCollection<Message>(); // set on batch and sent.
					ISingleCollection<Message> objMessage2ResponseCollection = new SingleCollection<Message>(); // used to respond deferred

					if(objMessageCollection.size() == 0)
					{
						BHS objBHS = new BHS();
						objBHS.setBatchControlID(objHL7Batch.getBatchControlID());
						objBHS.setBatchFieldSeparator('|');
						objBHS.setBatchEncodingChars('^','&','~','\\','#');

						BTS objBTS = new BTS();
						objBTS.setBatchMessageCount(""+objAckCollection.size());
						IHL7Batch objACKBatch = new HL7Batch(objBHS,objBTS,objAckCollection);
						System.out.println("Sending Batch.......");

						IHL7BatchFile objBatchFile = new HL7BatchFile();
						ISingleCollection<IHL7Batch> objIHL7BatchCollection = new SingleCollection<IHL7Batch>();
						objIHL7BatchCollection.add(objACKBatch);
						objBatchFile.setHL7BatchCollection(objIHL7BatchCollection);
						objClientSession.sendBatch(objBatchFile);
					}

					for(Message objMessage : objMessageCollection)
					{
						ACK acknowledgement = null;
						//ACK is fetched only when Deferred response is dispatched
						if(objMessage.getMessageStructure().equals(EnumMessageStructure.ACK.getValue()))  
						{
							System.out.println("ACK received for Deferred response By User Process Handler");
						}
						//check for query
						else if(objMessage.isQuery())
						{
							//Code block of Deferred Query 
							if(((AbstractQuery)objMessage).isDeferred())
							{
								acknowledgement = generateAcknowledgement(objMessage);
								objAckCollection.add(acknowledgement);

								Message response = generateResponse(objMessage);
								objMessage2ResponseCollection.add(response);

							}
							//Code block of Immediate Query
							else
							{
								Message response = generateResponse(objMessage);
								objAckCollection.add(response);
							}
						}
						//Code block of ACK
						else
						{
							acknowledgement = generateAcknowledgement(objMessage);

							objAckCollection.add(acknowledgement);
						}
					}

					// Ack for Batch
					if(objAckCollection.size()>0)
					{

						BHS objBHS = new BHS();
						objBHS.setBatchControlID(objHL7Batch.getBatchControlID());
						objBHS.setBatchFieldSeparator('|');
						objBHS.setBatchEncodingChars('^','&','~','\\','#');

						BTS objBTS = new BTS();
						objBTS.setBatchMessageCount(""+objAckCollection.size());
						IHL7Batch objACKBatch = new HL7Batch(objBHS,objBTS,objAckCollection);
						System.out.println("Sending Batch.......");

						IHL7BatchFile objBatchFile = new HL7BatchFile();
						ISingleCollection<IHL7Batch> objIHL7BatchCollection = new SingleCollection<IHL7Batch>();
						objIHL7BatchCollection.add(objACKBatch);
						objBatchFile.setHL7BatchCollection(objIHL7BatchCollection);
						objClientSession.sendBatch(objBatchFile);
					}

					// Responding Deferred..
					for(Message objMessage : objMessage2ResponseCollection)
					{
						objClientSession.sendMessage(objMessage);
					}

					synchronized (this)
					{
						System.out.println("Server : before wait");
						this.wait(6000);	
						System.out.println("Server : after wait");
					}
				}
			}
			catch(IOException ioe)
			{
				ioe.printStackTrace();
			} catch (InterruptedException e)
			{
				e.printStackTrace();
			}
		}

		/**
		 * This method is implementation of IProcesshandler interface.
		 * This method is invoked when any user establishes connection with Server. 
		 * @param objClientSession session of remote end
		 */
		public void OnConnect(ClientSession objClientSession) 
		{
			/*
			 * Instantiating TransactionHandler which keeps track for the sending and receiving message 
			 * and does verification of each message during transaction.
			 * User can provide his own implementation for ServerSideTransactionHandler by implementing ITransactionHandler interface.
			 * if user wants verification for each message within transaction then user has to set it else not.
			 */
			objServerTransactionHandler = new TransactionHandler();
			
			objClientSession.setServerSideTransactionHandler(objServerTransactionHandler);
			objClientSession.setMessageFactory(objMessageFactory);
			objClientSession.acceptConnection(true);
		}

		/**
		 * This method is implementation of IProcesshandler interface.
		 * This method is invoked when SDK is not able to parse received message.
		 * @param objClientSession 
		 */
		public void OnErrorReceive(ClientSession objClientSession)
		{
			//user code to generate error ACK to send 
			System.out.println("Error Occured"+objClientSession.getErrorCode());
		}

		/**
		 * This method is automatically invoked when Message is received from remote system.
		 * User provides the implementation of this method.
		 * Simulation of user code is demonstrated below.
		 * @param objClientSession instance of Client Session
		 */
		public void OnMessageReceive(ClientSession objClientSession) throws InvalidMessageException
		{
			Message receivedMessage = objClientSession.getMessage();

			try
			{

				/* 
				 * When user send Deferred response,ACK message is received from remote client end.
				 * ACK is fetched only when Deferred response is dispatched.
				 * Following code block handles Acknowledgment received for deferred response sent.
				 */
				if (receivedMessage.getMessageStructure().equals(EnumMessageStructure.ACK.getValue()))  
				{
					System.out.println("ACK received for Deferred response by User Process Handler");
				}

				/*
				 * Check for Query Message received from other systems
				 */
				else if(receivedMessage.isQuery())
				{
					if(receivedMessage.getMessageStructure().equals(EnumMessageStructure.QCN_J01.getValue()))
					{
						System.out.println("QCN_J01 Arrived at Server.");
					}
					//Handle Query Message with deferred priority 
					else if(((AbstractQuery)receivedMessage).isDeferred())
					{
						String strFilePath = null;
						try
						{
							strFilePath = "E:\\Client" + i++ + ".hl7"; //reader.readLine();

							HL7Serializer objHL7Serializer = new HL7Serializer();
							objHL7Serializer.serialize(receivedMessage.getSegmentSet(), strFilePath);

							System.out.print("Message serialized successfully\n");
						}
						catch(IOException ioe)
						{
							ioe.printStackTrace();
						}

						ACK acknowledgement = generateAcknowledgement(receivedMessage);

						objClientSession.sendMessage(acknowledgement);

						Message response = generateResponse(receivedMessage);

						if(((AbstractQuery)receivedMessage).isBatchRSPExpected())
						{
							AbstractQuery receivedQuery = (AbstractQuery)receivedMessage;
							BHS objBHS = new BHS();
							objBHS.setBatchControlID(receivedMessage.getHeader().getMessageControlID().getValue().toString());
							objBHS.setBatchFieldSeparator('|');
							objBHS.setBatchEncodingChars('^','&','~','\\','#');

							BTS objBTS = new BTS();
							objBTS.setBatchMessageCount(""+1);

							ISingleCollection<Message> objMessageCollection = new SingleCollection<Message>();
							objMessageCollection.add(response);

							IHL7Batch objBatchInResponse2Query = new HL7Batch(objBHS,objBTS,objMessageCollection);
							ISingleCollection<Segment> objQuerySegmentCollection = receivedQuery.getQuerySegments();
							if(objQuerySegmentCollection!=null)
							{

								if (objQuerySegmentCollection.elementAt(0) instanceof QPD)
								{
									QPD objQPD = (QPD) objQuerySegmentCollection.elementAt(0);

									RCP objRCP = null;

									if (objQuerySegmentCollection.elementAt(1) instanceof RCP) {
										objRCP = (RCP) objQuerySegmentCollection.elementAt(1);

									}
									objBatchInResponse2Query.setQuerySegments(objQPD,objRCP );
								}
							}
							IHL7BatchFile objBatchFile = new HL7BatchFile();
							ISingleCollection<IHL7Batch> objIHL7BatchCollection = new SingleCollection<IHL7Batch>();
							objIHL7BatchCollection.add(objBatchInResponse2Query);
							objBatchFile.setHL7BatchCollection(objIHL7BatchCollection);
							objClientSession.sendBatch(objBatchFile);
						}
						else
						{
							objClientSession.sendMessage(response);
						}
					}
					//Send response for Query Message with Immediate priority 
					else
					{
						Message response = generateResponse(receivedMessage);

						if(((AbstractQuery)receivedMessage).isBatchRSPExpected())
						{
							AbstractQuery receivedQuery = (AbstractQuery)receivedMessage;
							BHS objBHS = new BHS();
							objBHS.setBatchControlID(receivedMessage.getHeader().getMessageControlID().getValue().toString());
							objBHS.setBatchFieldSeparator('|');
							objBHS.setBatchEncodingChars('^','&','~','\\','#');

							BTS objBTS = new BTS();
							objBTS.setBatchMessageCount(""+1);

							ISingleCollection<Message> objMessageCollection = new SingleCollection<Message>();
							objMessageCollection.add(response);

							IHL7Batch objBatchInResponse2Query = new HL7Batch(objBHS,objBTS,objMessageCollection);
							ISingleCollection<Segment> objQuerySegmentCollection = receivedQuery.getQuerySegments();
							if(objQuerySegmentCollection!=null)
							{

								if (objQuerySegmentCollection.elementAt(0) instanceof QPD)
								{
									QPD objQPD = (QPD) objQuerySegmentCollection.elementAt(0);

									RCP objRCP = null;

									if (objQuerySegmentCollection.elementAt(1) instanceof RCP) {
										objRCP = (RCP) objQuerySegmentCollection.elementAt(1);

									}
									objBatchInResponse2Query.setQuerySegments(objQPD,objRCP );
								}

							}
							IHL7BatchFile objBatchFile = new HL7BatchFile();
							ISingleCollection<IHL7Batch> objIHL7BatchCollection = new SingleCollection<IHL7Batch>();
							objIHL7BatchCollection.add(objBatchInResponse2Query);
							objBatchFile.setHL7BatchCollection(objIHL7BatchCollection);
							objClientSession.sendBatch(objBatchFile);
						}
						else
						{
							objClientSession.sendMessage(response);
						}
					}
				}
				//Send Acknowledgment when event is received from other system.
				else
				{
					ACK acknowledgement = generateAcknowledgement(receivedMessage);
					objClientSession.sendMessage(acknowledgement);
				}
			}
			catch(InvalidMessageException Ime)
			{
				Ime.printStackTrace();
			}
			catch(IOException ioe)
			{
				ioe.printStackTrace();
			}
		}

		/**
		 * Closes the Connection.
		 * @param objClientSession object of Client Session.
		 */
		public void onClose(ClientSession objClientSession) 
		{
			System.out.println("On Close");
		}

		/**
		 * This method is invoked when exception is fetched from remote end.
		 * @ex Exception fetched
		 * @buffer for which exception is received
		 */
		public void onException(Exception ex, byte[] buffer) 
		{
			System.out.println("In On Exception Receiced : Printing Stacktrace...");
			System.out.println(ex.getMessage());
			System.out.println("End of Stacktrace....");
			try
			{
				System.out.println("Byte Buffer is : ");
				ByteArrayOutputStream objByteArrayOutputStream = new ByteArrayOutputStream();
				objByteArrayOutputStream.write(buffer);

				objByteArrayOutputStream.writeTo(System.out);
			}
			catch (Exception e)
			{
				e.printStackTrace();
			}
		}

		/**
		 * This method is invoked when exception is fetched from remote end.
		 * @ex Exception fetched
		 * @objISegmentSet for which Segment Set is Received.
		 */
		public void onException(Exception ex, ISegmentSet objISegmentSet)
		{
			System.out.println("In On Exception Receiced : Printing Stacktrace...");
			System.out.println(ex.getMessage());
			System.out.println("End of Stacktrace....");
			try
			{
				System.out.println("Segment Set is : ");
				ISingleCollection<ISegment> objISegmentSetCollection = objISegmentSet.getList();
				if(objISegmentSetCollection!=null)
				{
					System.out.println("Received Segment Set Contains following Segments:");
					for(ISegment objISegment : objISegmentSetCollection)
					{
						System.out.println(objISegment.getName());
					}
				}
			}
			catch (Exception e)
			{
				e.printStackTrace();
			}
		}
		
		/**
		 * This method simulates user action to generate Response for Query message received.
		 * This method is demonstrated for test purpose only.
		 * In the actual scenario It is User's responsibility to generates response & sends it on client Session.
		 * In this method as we have demonstrated response generation for Query (QRY_A19) message.
		 * Response specific to QRY_A19 message is ADR_A19.
		 * Code block below first checks the priority of Query message.Afterwards it creates response message ADR_A19 by manually populating it.
		 * The values used for population of Response message are for test purpose only.   
		 * @param enumMessageStructures enum value of Message Structure
		 * @throws IOException if input/output operation fails
		 */
		Message generateResponse(Message objHL7Message) throws IOException
		{
			Message response = null;
			String strMessageStructure = objHL7Message.getMessageStructure();
			String strRecievedMsgCntlID = objHL7Message.getHeader().getMessageControlID().getValue().toString();
			AbstractQuery objAbstractQuery = (AbstractQuery)objHL7Message;
			String strReceivedQueryId = objAbstractQuery.getQueryIdentifier().getValue().toString();
			switch(EnumMessageStructure.valueOf(strMessageStructure))
			{
			case QBP_Q21:
				if("MSG0011".equalsIgnoreCase(objHL7Message.getHeader().getMessageControlID().getValue().toString()))
				{
	                //This will extract Query id from QPD segment and set it in QAK segment. 
	                QPD objQPDSegment = (QPD)objHL7Message.getSegment(EnumSegments.HL7_SEG_QPD).elementAt(0);
	                
					RSP_K21 objRSP_K21 = (RSP_K21)new ADTRecepient().createMessage(EnumMessageCode.RSP, EnumTriggerEvent.K21);

					//Populate RSP_K23 MSH (message header segment)
					MSH objNewMSH = objPopulateTest.populateMSH();
					objNewMSH.setMessageType(EnumMessageCode.RSP.getValue(), EnumTriggerEvent.K21.getValue(), EnumMessageStructure.RSP_K21.getValue());
					objNewMSH.setMessageControlID("MSG0011"+messageControlId++);
					objRSP_K21.setHeader(objNewMSH);

					MSA objMSA = objPopulateTest.populateMSA();
					objMSA.setMessageControlID(strRecievedMsgCntlID);
					objMSA.setExpectedSequenceNumber("1234567");
					objRSP_K21.setMessageAcknowledgmentSegment(objMSA);

					QAK objQAK = objPopulateTest.populateQAK();
					objQAK.setQueryTag(objQPDSegment.getQueryTag().getValue().toString());
					objRSP_K21.setQueryAcknowledgementSegment(objQAK);

					QPD objQPD = objPopulateTest.populateQPD();
					objRSP_K21.setQueryParameterDefinitionSegment(objQPD);

					DSC objDSC = objPopulateTest.populateDSC();
	                objDSC.setContinuationStyle("I");
	                objRSP_K21.setContinuationPointerSegment(objDSC);

					response = objRSP_K21;
				}
				else
				{
	                //This will extract Query id from QPD segment and set it in QAK segment.
	                QPD objQPDSegment = (QPD)objHL7Message.getSegment(EnumSegments.HL7_SEG_QPD).elementAt(0);
	                
					RSP_K21 objRSP_K21 = (RSP_K21)new ADTRecepient().createMessage(EnumMessageCode.RSP, EnumTriggerEvent.K21);
					
					//Populate RSP_K23 MSH (message header segment)
					MSH objNewMSH = objPopulateTest.populateMSH();
					objNewMSH.setMessageType(EnumMessageCode.RSP.getValue(), EnumTriggerEvent.K21.getValue(), EnumMessageStructure.RSP_K21.getValue());
					objNewMSH.setMessageControlID("MSG0012"+messageControlId++);
					objRSP_K21.setHeader(objNewMSH);

					MSA objMSA = objPopulateTest.populateMSA();
					objMSA.setMessageControlID(strRecievedMsgCntlID);
					objMSA.setExpectedSequenceNumber("1234567");
					objRSP_K21.setMessageAcknowledgmentSegment(objMSA);

	                QAK objQAK = objPopulateTest.populateQAK();
	                objQAK.setQueryTag(objQPDSegment.getQueryTag().getValue().toString());
	                objRSP_K21.setQueryAcknowledgementSegment(objQAK);

					QPD objQPD = objPopulateTest.populateQPD();
					objRSP_K21.setQueryParameterDefinitionSegment(objQPD);

					response = objRSP_K21;
				}
				break;
			case QBP_E03:
				{	
					IGroup objQIGroup = objHL7Message.getGroup(EnumSegments.HL7_GROUP_QUERY_INFORMATION).elementAt(0);
					QPD objQPDSegment = (QPD) objQIGroup.getSegment(EnumSegments.HL7_SEG_QPD).elementAt(0);
						
					RSP_E03 objRSP_E03 = (RSP_E03)new ClaimsAndReimbursementRecepient().createMessage(EnumMessageCode.RSP, EnumTriggerEvent.E03);
					
					MSH objNewMSH = objPopulateTest.populateMSH();
					objNewMSH.setMessageType(EnumMessageCode.RSP.getValue(), EnumTriggerEvent.E03.getValue(), EnumMessageStructure.RSP_E03.getValue());
					objNewMSH.setMessageControlID("MSG0012"+messageControlId++);
					objRSP_E03.setHeader(objNewMSH);
					
					MSA objMSA = objPopulateTest.populateMSA();
					objMSA.setMessageControlID(strRecievedMsgCntlID);
					objMSA.setExpectedSequenceNumber("1234567");
					objRSP_E03.setMessageAcknowledgmentSegment(objMSA);
					
					IMap objMessageMap = MessageMapReader.createInstance().getMessageMap(EnumMessageCode.RSP, EnumTriggerEvent.E03);
					
					IMap objQueryACKIPRGroupMap = objMessageMap.getGroupMap(EnumSegments.HL7_GROUP_QUERY_ACK_IPR);

					IGroup objQueryACKIPRGroup = new Group(EnumSegments.HL7_GROUP_QUERY_ACK_IPR, objQueryACKIPRGroupMap);
					
	                QAK objQAK = objPopulateTest.populateQAK();
	                objQAK.setQueryTag(objQPDSegment.getQueryTag().getValue().toString());
	                objQueryACKIPRGroup.addSegment(EnumSegments.HL7_SEG_QAK, objQAK);

					QPD objQPD = objPopulateTest.populateQPD();
					objQueryACKIPRGroup.addSegment(EnumSegments.HL7_SEG_QPD, objQPD);
					
					objRSP_E03.addQueryACKIPRGroup(objQueryACKIPRGroup);

					response = objRSP_E03;
				}	
					break;
				
		
			}
			return response;
		}
		/**
		 * This method simulates user action to generate Acknowledgment for message received.
		 * This method is demonstrated for test purpose only.
		 * In the actual scenarion, it is User's responsibility to generates Acknowledgment & sends it on client Session. 
		 * @param objReceivedMessage specified Message object
		 * @return ACK instance of Acknowledgment
		 */
		public ACK generateAcknowledgement(Message objReceivedMessage)
		{
			strMessageControlid = "MSG90231"+messageControlId++;
			
			IMessageMapReader objMessageMapReader = MessageMapReader.createInstance();
			IMap objMessageMap = objMessageMapReader.getMessageMap(EnumMessageCode.ACK, null);

			ACK ackMessage = new ACK(StandardMethods.getEnumTriggerEvent(objReceivedMessage.getTriggerEvent()), objMessageMap);
			MSH objMSH = objPopulateTest.populateMSH();
			objMSH.setMessageType(EnumMessageCode.ACK.getValue(), objReceivedMessage.getTriggerEvent(),EnumMessageStructure.ACK.getValue());
			objMSH.setMessageControlID(strMessageControlid);
			ackMessage.setHeader(objMSH);
			
			//MSA Segment
			MSA objMSA = new MSA();
			objMSA.setAcknowledgmentCode("AA");
			objMSA.setMessageControlID(objReceivedMessage.getHeader().getMessageControlID().getValue().toString());
			objMSA.setExpectedSequenceNumber("1234567");
			ackMessage.setMessageAcknowledgmentSegment(objMSA);
			return ackMessage;
		}
	}
}
