<?xml version="1.0" encoding="UTF-8"?>
<Export generator="Cache" version="25" zv="Cache for Windows (x86-64) 2012.2.5 (Build 962U)" ts="2017-08-14 12:56:09">
<Class name="AGMPI.Adapters.AlertInbound">
<Super>Ens.InboundAdapter</Super>
<TimeChanged>64204,48429.622735</TimeChanged>
<TimeCreated>64204,48429.622735</TimeCreated>

<Method name="OnTask">
<ReturnType>%Status</ReturnType>
<Implementation><![CDATA[
	set tSC=$$$OK
	
	do {
		&sql(SELECT COUNT(*) INTO :numalerts FROM AGMPI_Alerts.AlertItem WHERE ReportedTimestamp IS NULL)
		if 'numalerts { quit }  // Go to sleep for the duration of the polling period.

		set req=##class(Ens.AlertRequest).%New()
		
		// If just one alert, report it.
		if numalerts=1 {
			&sql(SELECT ID INTO :id FROM AGMPI_Alerts.AlertItem WHERE ReportedTimestamp IS NULL ORDER BY CreatedTimestamp)
			set alertobj=##class(AGMPI.Alerts.AlertItem).%OpenId(id)
			if $IsObject(alertobj) {
				set req.SourceConfigName=alertobj.SourceConfigName
				set req.AlertText=alertobj.AlertText
				set alertobj.ReportedTimestamp=$zdt($h,3,1)
				do alertobj.%Save()
			}
			else {
				set req.SourceConfigName=..BusinessHost.%ConfigName
				set req.AlertText="Unable to open alert object "_id
			}
			set tSC=..BusinessHost.ProcessInput(req)
			quit
		}
		
		// If more than one alert, send a digest.
		set nl=$c(13,10)
		kill alerts
		
		&sql(DECLARE C1 CURSOR FOR SELECT ID, Category INTO :id, :cat FROM AGMPI_Alerts.AlertItem WHERE ReportedTimestamp IS NULL ORDER BY CreatedTimestamp)
		&sql(OPEN C1)
		&sql(FETCH C1)
		
		while 'SQLCODE {
			if ((id="") || ('##class(AGMPI.Alerts.AlertItem).%ExistsId(id))) {
				&sql(FETCH C1)
				continue
			}
			
			if cat="" { set cat="Unknown" }
			
			set alertobj=##class(AGMPI.Alerts.AlertItem).%OpenId(id)
			set alertobj.ReportedTimestamp=$zdt($h,3,1)
			do alertobj.%Save()
			
			set alerts(0)=$g(alerts(0))+1
			
			if +$g(alerts(cat))=0 {
				set alerts(cat)=1
				set alerts(cat,0)=alertobj.AlertText
			}
			else {
				set alerts(cat)=$g(alerts(cat))+1
			}
			
			&sql(FETCH C1)
		}
		
		&sql(CLOSE C1)

		set req.SourceConfigName="Multiple alerts"
		set req.AlertText=alerts(0)_$s(alerts(0)=1:" alert",1:" alerts")_" reported"_nl_nl
		
		set cat=0
		for {
			set cat=$o(alerts(cat))
			quit:cat=""
			
			set req.AlertText=req.AlertText_"Category '"_cat_"': "_alerts(cat)_$s(alerts(cat)=1:" alert",1:" alerts")_nl
			if alerts(cat)>1 { set req.AlertText=req.AlertText_"Sample alert: " }
			set req.AlertText=req.AlertText_alerts(cat,0)_nl_nl
		}

		set tSC=..BusinessHost.ProcessInput(req)
		
	} while 0
	
	quit tSC
]]></Implementation>
</Method>
</Class>


<Class name="AGMPI.Adapters.HLOGlobalInbound">
<IncludeCode>EnsHL7</IncludeCode>
<Super>Ens.InboundAdapter</Super>
<TimeChanged>64203,49383.484811</TimeChanged>
<TimeCreated>61592,31859.341221</TimeCreated>

<Property name="ReceivingFacilityName">
<Description>
Name of the Receiving Facility to filter HL7 messages.</Description>
<Type>%String</Type>
<Parameter name="MAXLEN" value="200"/>
</Property>

<Property name="MaxNmbrMsgs">
<Description>
Maximum number of messages to retrieve/send per poll/task. </Description>
<Type>%Integer</Type>
</Property>

<Property name="Throttle">
<Description>
Time to hang before processing another message,
used to manage the throughput.</Description>
<Type>%Integer</Type>
</Property>

<Property name="NmbrMsgsSnt">
<Description>
The number of messages retrieved.</Description>
<Type>%Integer</Type>
</Property>

<Property name="AInfo">
<Description>
Information to send an alert from the business service
 if populated.</Description>
<Type>%String</Type>
</Property>

<Property name="SiteID">
<Description>
Site ID.  This is the STATION NUMBER</Description>
<Type>%String</Type>
</Property>

<Parameter name="SETTINGS">
<Type>%String</Type>
<Default>ReceivingFacilityName, MaxNmbrMsgs, Throttle, SiteID</Default>
</Parameter>

<Method name="OnTask">
<ReturnType>%Status</ReturnType>
<Implementation><![CDATA[
  set $ZT="Trap", tSC=$$$OK

  // Initialize a start time variable.
  set tStartTime = $P($H,",",2)	
  // Initialize the Alert Information property to the null string.
  set ..AInfo=""
  // Initialize the number of messages sent during this connection.
  set ..NmbrMsgsSnt=0
  // Initialize a variable(Flag) to use to quit when we reach the maximum
  // number of messages.
  set tQuitAll=0
  // Set the field delimiter for the HLB data set.
  set U = "^"
  // Set the initial HLB index value to zero.
  set tIENB=0
  // Set the ^HLB QUEUE Node index variables.
  set tQueue="", tLink=""
  
  // Indices of the HLB queue are;
  // the string "QUEUE"
  // the string "OUT"
  // the HLO Logical Link and Port associated with it
  // the Queue Type
  // ^HLB("QUEUE","OUT",tLink,tQueue,tIENB)

  // Outer loop going through the tLink values   
  do { 
	  // If the ReceivingFacilityName variable is not set we will not process any
	  //  messages.
	  if (""=..ReceivingFacilityName) {
		  set ..AInfo=..AInfo_" No Receiving Facility Name is set for the Inbound HLO Global Adapter, no messages are being processed." 
  	  	  do ..BusinessHost.SendAlert(##Class(Ens.AlertRequest).%New($LB(..BusinessHost.%ConfigName,"ERROR in Configuration", ..AInfo)))
		  quit //exit the do loop
  	  }

	  // Get the tLink index
	  set tLink = $O(^HLB("QUEUE","OUT",tLink))
	
	  // If the tLink variable is null we do not have any more nodes to process
	  if (tLink="") { quit }
	  
	  // Loop through the tQueue values at the tLink index
	  for {
		  // Get the tQueue index
		  set tQueue = $O(^HLB("QUEUE","OUT",tLink,tQueue))
	  
		  // If the tQueue variable is null we do not have any more nodes at this level to process.
		  if (tQueue="") { quit }
	  
		  //Loop through the IENs at the tLink.tQueue index
		  for {
			  // Get the tIENB index
			  set tIENB = $O(^HLB("QUEUE","OUT",tLink,tQueue,tIENB))
	  
			  // If the TIENB varible is zero we do not have an IEN to process
			  if (tIENB="") { quit }
	  
			  // Initialize the Node Data variable.
			  set tNodeData = ""
	  
			  // if there's no data within the node we skip this entry and go to the next
			  if '($D(^HLB(tIENB,0),tNodeData)#10) { continue }
	        
			  // Get the message direction from the Node Data
			  set tMessageDirection=$ZCONVERT($p(tNodeData,U,4),"U")
	  
			  // If the direction is not outbound we skip this entry and go to the next
			  if '(tMessageDirection = "O") { continue }
	  
			  // Get the date processed from the Node Data
			  set tDateProcessed=$p(tNodeData,U,16)
	  
			  // If the Date Processed is not empty, this message has already been processed, we
			  //  skip this entry and go to the next
			  if '(tDateProcessed="") { continue }
	  
			  // Get the A index 'tIENA' from the Node Data.
			  set tIENA=$p(tNodeData,U,2)
	  
			  // Get the MSH segment from the HLB tIENB.1 and tIENB.2 node entries
			  set tMSHsegment=$G(^HLB(tIENB,1))_$G(^HLB(tIENB,2)) 

              // Reset the Field Separator variable to the empty string before 
              //  reading the value from the current MSH segment
              set tFieldSeparator=""
         
			  // The field separator is the 4th character of the MSH segment.
			  set tFieldSeparator=$E(tMSHsegment,4)
			  
			  // If the field separator is missing we exit the loop
			  if (tFieldSeparator="") {continue}
			  
			  // Reset the Copmponent Separator value to the empty string before 
			  //  reading the value from the current MSH segment
              set tComponentSeparator=""
			  
			  // The component separator is the 5th character of the MSH segment.
			  set tComponentSeparator=$E(tMSHsegment,5)
			  
			  // If the component separator is missing we exit the loop
			  if (tComponentSeparator="") {continue}

              // Reset the Message Type variable to the empty string before 
              //  reading the value from the current MSH segment
              set tMessageType=""

			  // Get the Message Type
			  set tMessageType=$P(tMSHsegment,tFieldSeparator,9)
			  
			  // If the Message Type is missing we exit the loop
			  if (tMessageType="") {continue}
 	  
			  // We set the MessageType field to the MessageCode and Trigger Event subfields.
			  set $p(tMSHsegment,tFieldSeparator,9) = $p(tMessageType,tComponentSeparator,1,2)
 	  
			  // Get the segment name wthin the MSH segment, if we do not have a field separator
			  //  we cannot get the segment name
			  set tSegmentName = $p(tMSHsegment,tFieldSeparator,1)
 	  
			  // If we do not have a MSH segment we do not process this message
			  if '(tSegmentName = "MSH") { continue }

			  // If the receiving facility of the message doesn't match the ReceivingFacility 
			  //  in the parameter, we do not process this message.
			  if '(..ReceivingFacilityName=$p(tMSHsegment,tFieldSeparator,5)) { continue }

			  // -------------------------------------------------------------------------
			  // We've identified a message that should be sent to the receiving facility
			  // Build the HL7 message to send to the RPMS Service
	  
			  // Set the segment separator
			  set tSegmentSeparator=$c(13)
	        
			  // Add the MSH segment to the text string
			  set tMessageText=tMSHsegment_tSegmentSeparator
            
			  // Set the segment index to zero
			  set tSegmentIndex=0
      
			  // Set the segment data to the null sting to begin with
			  set tSegmentData=""
			  set tSegmentData2=""


			  // Loop through the ^HLA indices for the message segments.
			  // AG*7.2*4/CR 7694 - Replaced algorithm that didn’t correctly account for long segments
			  // This code uses the same logic as HLNEXT^HLOMSG.
			  set start=0,tSegmentIndex=0
			  for {
				  // Loop through the segments
				  set tSegmentIndex=$o(^HLA(tIENA,1,tSegmentIndex))
				  quit:'tSegmentIndex
				  set tSegmentData=$g(^HLA(tIENA,1,tSegmentIndex,0))
				  // If this is a blank node and we previously had data, append the segment separator.
				  if start && (tSegmentData="") { set tMessageText=tMessageText_tSegmentSeparator,start=0 }
				  // If this node has data, append it. Don't append a segment separator, because there
				  // might be more of this segment in the next node.
				  if tSegmentData'="" { set tMessageText=tMessageText_tSegmentData,start=1 }
			  }
			  // Make sure we end with a segment separator if necessary.
			  if start { set tMessageText=tMessageText_tSegmentSeparator }

			  TStart

			  // Create the HL7 message document to send to the business 
			  //  host that will route the message
			  set tHL7obj=##class(EnsLib.HL7.Message).ImportFromString(tMessageText)
            
			  // Check to see that the hl7obj is an object
			  set tObjectError= $ISOBJECT(tHL7obj)
	  
			  // Send a message to the ENS.Alert Process if we fail to create an object to send
			  If 'tObjectError {
				  set tSC=%objlasterror
				  set ..AInfo=" Failed to create an HL7 message with the information retrieved from the HLA global, IEN= "_tIENA
				  set ..AInfo=..AInfo_" ERROR:= "_##class(%SYSTEM.Status).GetErrorText(tSC)
				  do ..BusinessHost.SendAlert(##Class(Ens.AlertRequest).%New($LB(..BusinessHost.%ConfigName,"There was an issue creating a valid HL7 message in the HLOGlobalInbound Adapter: ", ..AInfo)))
				  set ..AInfo=""
				  tRollBack
				  continue
			  }
			
			  // Send the message to the Business Host  
			  set tBusinessHostResponse=..BusinessHost.ProcessInput(tHL7obj)
			  
			  // Increase the number of messages we've sent this period
			  set ..NmbrMsgsSnt=..NmbrMsgsSnt+1
			  
			  // If we sent a message to the production,we need to update the 16th field within
			  //  the HLB global with the Fileman date.
			  set $p(^HLB(tIENB,0),U,16)=..GetFilemanDateTime(0) 
	  
			  // Remove the ^HLB("QUEUE","OUT",tLink,tQueue,tIENB) entry
			  kill ^HLB("QUEUE","OUT",tLink,tQueue,tIENB)
	  
			  // decrement the HLC counter, if it exist
			  if (+$G(^HLC("QUEUECOUNT","OUT",tLink,tQueue))) {
				  set tTemp = $i(^HLC("QUEUECOUNT","OUT",tLink,tQueue),-1) 
			  }
			
			   TCommit
			  If ( ..NmbrMsgsSnt =..MaxNmbrMsgs)  {
				  set tQuitAll=1
				  quit
			  }
			  // Set the Current Time variable
			  set tCurrentTime = $P($H,",",2)
			  // Set the processing time, if the start time is greater than the
			  //  current time (we passed midnight) and will always set the 
			  //  processing time to a value greater than the call interval. 
			  If tStartTime > tCurrentTime {
				  set tProcessingTime = tStartTime - tCurrentTime
			  }
			  else {
				  set tProcessingTime = tCurrentTime - tStartTime
			  }
			  // If the processing time is greater than the Call Interval
			  //  return control to the Service that called the adapter.
			  if (tProcessingTime > ..CallInterval) {
				  set tQuitAll=1
				  quit
			  }
			  HANG (..Throttle/1000)
			  if (tQuitAll) {quit}
		  } // Close the IEN loop
		  if tQuitAll {quit}
	  } // Close the tQueue loop
  }While '(tQuitAll) // Close the tLink loop
  quit $$$OK

Trap
	// We erred out, set the error information and roll back the last transaction.
	set $ZT=""
	TRollback
	set tSC=$$$EnsSystemError
	do ..BusinessHost.SendAlert(##Class(Ens.AlertRequest).%New($LB(..BusinessHost.%ConfigName,"There was an error in the HLOGlobalInbound Adapter: ", tSC)))
	quit $$$OK
]]></Implementation>
</Method>

<Method name="GetFilemanDateTime">
<Description>
Returns the date/time in FileManFormat</Description>
<ClassMethod>1</ClassMethod>
<FormalSpec>pDays:%Integer=0</FormalSpec>
<ReturnType>%String</ReturnType>
<Implementation><![CDATA[
	set tCurrentDateTime = $H
	set $P(tCurrentDateTime,",",1)=$P(tCurrentDateTime,",",1)+pDays
	set tFileManDate = ($ZDATETIME(tCurrentDateTime,8,1,9)-17000000)
	set tCurrentTime = $P(tCurrentDateTime,",",2)
	set tCurrentTimeFormatted = $ZTIME(tCurrentTime,2)
	set tFileManTime = $P(tCurrentTimeFormatted,":",1)_$P(tCurrentTimeFormatted,":",2)
	quit (tFileManDate_"."_tFileManTime)
]]></Implementation>
</Method>
</Class>


<Class name="AGMPI.Alerts.AlertItem">
<Super>%Persistent</Super>
<TimeChanged>64244,54447</TimeChanged>
<TimeCreated>64203,52817.445651</TimeCreated>

<Property name="SourceConfigName">
<Type>%String</Type>
<Parameter name="MAXLEN" value="128"/>
</Property>

<Property name="AlertText">
<Type>%String</Type>
<Parameter name="MAXLEN" value="500"/>
</Property>

<Property name="CreatedTimestamp">
<Type>%TimeStamp</Type>
</Property>

<Property name="Category">
<Type>%String</Type>
</Property>

<Property name="ReportedTimestamp">
<Type>%TimeStamp</Type>
</Property>

<Index name="ReportedTimestampIdx">
<Properties>ReportedTimestamp</Properties>
</Index>

<Index name="CreatedTimestampIdx">
<Properties>CreatedTimestamp</Properties>
</Index>

<Storage name="Default">
<Type>%Library.CacheStorage</Type>
<DataLocation>^AGMPI.Alerts.AlertItemD</DataLocation>
<DefaultData>AlertItemDefaultData</DefaultData>
<IdLocation>^AGMPI.Alerts.AlertItemD</IdLocation>
<IndexLocation>^AGMPI.Alerts.AlertItemI</IndexLocation>
<StreamLocation>^AGMPI.Alerts.AlertItemS</StreamLocation>
<ExtentSize>100000</ExtentSize>
<Data name="AlertItemDefaultData">
<Structure>listnode</Structure>
<Subscript/>
<Value name="1">
<Value>%%CLASSNAME</Value>
</Value>
<Value name="2">
<Value>SourceConfigName</Value>
</Value>
<Value name="3">
<Value>AlertText</Value>
</Value>
<Value name="4">
<Value>CreatedTimestamp</Value>
</Value>
<Value name="5">
<Value>Category</Value>
</Value>
<Value name="6">
<Value>ReportedTimestamp</Value>
</Value>
</Data>
</Storage>
</Class>


<Class name="AGMPI.Process.AlertProcess">
<Description>
</Description>
<ClassType>persistent</ClassType>
<Super>Ens.BusinessProcessBPL</Super>
<TimeChanged>64244,54447</TimeChanged>
<TimeCreated>61592,35734.428636</TimeCreated>

<XData name="BPL">
<Description>
BPL Definition</Description>
<XMLNamespace>http://www.intersystems.com/bpl</XMLNamespace>
<Data><![CDATA[
<process language='objectscript' request='Ens.AlertRequest' response='Ens.Response' height='2500' width='2000' >
<context>
<property name='AlertItem' type='AGMPI.Alerts.AlertItem' initialexpression='##class(AGMPI.Alerts.AlertItem).%New()' >
</property>
<property name='Delim' type='%String' initialexpression='$c(1)' >
</property>
<property name='Status' type='%Status' initialexpression='$$$OK' >
</property>
</context>
<sequence xend='200' yend='2250' >
<scope name='scope3' xpos='200' ypos='250' xend='200' yend='2150' >
<if name='AlertText' condition='$l(request.AlertText)' xpos='200' ypos='350' xend='200' yend='1700' >
<true>
<assign name="SourceConfigName" property="context.AlertItem.SourceConfigName" value="request.SourceConfigName" action="set" xpos='470' ypos='500' />
<assign name="AlertText" property="context.AlertItem.AlertText" value="$p(request.AlertText,context.Delim)" action="set" xpos='470' ypos='600' />
<assign name="Category" property="context.AlertItem.Category" value="$p(request.AlertText,context.Delim,2)" action="set" xpos='470' ypos='700' />
<if name='No Category' condition='context.AlertItem.Category=""' xpos='470' ypos='800' xend='470' yend='1050' >
<true>
<assign name="Category=&quot;Unknown&quot;" property="context.AlertItem.Category" value="&quot;MPI&quot;" action="set" xpos='605' ypos='950' />
</true>
</if>
<assign name="CreatedTimestamp" property="context.AlertItem.CreatedTimestamp" value="$zdt($h,3,1)" action="set" xpos='470' ypos='1150' />
<assign name="Save AlertItem" property="context.Status" value="context.AlertItem.%Save()" action="set" xpos='470' ypos='1250' />
<if name='Save error' condition='$$$ISERR(context.Status)' xpos='470' ypos='1350' xend='470' yend='1600' >
<true>
<throw name='SaveError' fault='"SaveError"' xpos='605' ypos='1500' />
</true>
</if>
</true>
<false>
<throw name='NoAlertText' fault='"NoAlertText"' xpos='200' ypos='500' />
</false>
</if>
<faulthandlers>
<catch name='NoAlertText' fault='"NoAlertText"' xpos='200' ypos='1800' xend='200' yend='350' >
<trace name='Error in alert process' value='"Error in Alert Process: No text in alert"' xpos='200' ypos='250' />
</catch>
<catch name='SaveError' fault='"SaveError"' xpos='200' ypos='1900' xend='200' yend='350' >
<trace name='Error in alert process' value='"Error in Alert Process: Save error: "_$System.Status.GetErrorCodes(context.Status)_" : "_$System.Status.GetOneStatusText(context.Status)' xpos='200' ypos='250' />
</catch>
<catchall xpos='200' ypos='2000' xend='200' yend='350' >
<trace name='Error in alert process' value='"Error in Alert Process: "_$System.Status.GetErrorCodes(..%Context.%LastError)_" : "_$System.Status.GetOneStatusText(..%Context.%LastError)' xpos='200' ypos='250' />
</catchall>
</faulthandlers>
</scope>
</sequence>
</process>
]]></Data>
</XData>

<Storage name="Default">
<Type>%Library.CacheStorage</Type>
</Storage>
</Class>


<Class name="AGMPI.Services.Alert">
<Super>Ens.BusinessService</Super>
<TimeChanged>64204,55168.307721</TimeChanged>
<TimeCreated>64204,54739.900937</TimeCreated>

<Parameter name="ADAPTER">
<Default>AGMPI.Adapters.AlertInbound</Default>
</Parameter>

<Method name="OnProcessInput">
<FormalSpec>pInput:Ens.AlertRequest,pOutput:%RegisteredObject</FormalSpec>
<ReturnType>%Status</ReturnType>
<Implementation><![CDATA[
	if ($IsObject(pInput) && (pInput.AlertText'="")) {
		do ..SendRequestAsync("EmailAlert",pInput)
	}

	quit $$$OK
]]></Implementation>
</Method>
</Class>
</Export>
