Example #1
0
        /// <summary>
        /// Generate a string containing the ACK message in response to the original message. Supply a string containing the original message (or at least the MSH segment).
        /// </summary>
        /// <returns></returns>
        string GenerateACK(string originalMessage)
        {
            // create a HL7Message object using the original message as the source to obtain details to reflect back in the ACK message
            HL7Message tmpMsg          = new HL7Message(originalMessage);
            string     trigger         = tmpMsg.GetHL7ItemValue("MSH-9.2")[0];
            string     originatingApp  = tmpMsg.GetHL7ItemValue("MSH-3")[0];
            string     originatingSite = tmpMsg.GetHL7ItemValue("MSH-4")[0];
            string     messageID       = tmpMsg.GetHL7ItemValue("MSH-10")[0];
            string     processingID    = tmpMsg.GetHL7ItemValue("MSH-11")[0];
            string     hl7Version      = tmpMsg.GetHL7ItemValue("MSH-12")[0];
            string     ackTimestamp    = DateTime.Now.Year.ToString() + DateTime.Now.Month.ToString() + DateTime.Now.Day.ToString() + DateTime.Now.Hour.ToString() + DateTime.Now.Minute.ToString();

            StringBuilder ACKString = new StringBuilder();

            ACKString.Append((char)0x0B);
            ACKString.Append("MSH|^~\\&|HL7Listener|HL7Listener|" + originatingSite + "|" + originatingApp + "|" + ackTimestamp + "||ACK^" + trigger + "|" + messageID + "|" + processingID + "|" + hl7Version);
            ACKString.Append((char)0x0D);
            ACKString.Append("MSA|CA|" + messageID);
            ACKString.Append((char)0x1C);
            ACKString.Append((char)0x0D);
            return(ACKString.ToString());
        }
        private string ConstructMessageDetails(string Hl7Message)
        {
            HL7Message message = new HL7Message(Hl7Message);

            string[] msgID           = message.GetHL7ItemValue("MSH-10");
            string[] msgType         = message.GetHL7ItemValue("MSH-9.1");
            string[] msgTrigger      = message.GetHL7ItemValue("MSH-9.2");
            string   msgDetailString = "";

            // construct the strings if the elements exist in the message
            if (!((msgID == null) || (msgID.Length == 0)))
            {
                msgDetailString += "_" + msgID[0];
            }
            if (!((msgType == null) || (msgType.Length == 0)))
            {
                msgDetailString += "_" + msgType[0];
            }
            if (!((msgTrigger == null) || (msgTrigger.Length == 0)))
            {
                msgDetailString += "_" + msgTrigger[0];
            }
            return(msgDetailString);
        }
Example #3
0
        /// <summary>
        /// Send each of the files provided
        /// </summary>
        protected override void ProcessRecord()
        {
            foreach (string path in paths)
            {
                // This will hold information about the provider containing the items that this path string might resolve to.
                ProviderInfo provider;

                // This will be used by the method that processes literal paths
                PSDriveInfo drive;

                // this contains the paths to process for this iteration of the loop to resolve and optionally expand wildcards.
                List <string> filePaths = new List <string>();

                // if the path provided is a directory, expand the files in the directory and add these to the list.
                if (Directory.Exists(path))
                {
                    filePaths.AddRange(Directory.GetFiles(path));
                }

                // not a directory, could be a wild-card or literal filepath
                else
                {
                    // expand wild-cards. This assumes if the user listed a directory it is literal
                    if (expandWildcards)
                    {
                        // Turn *.txt into foo.txt,foo2.txt etc. If path is just "foo.txt," it will return unchanged. If the filepath expands into a directory ignore it.
                        foreach (string expandedFilePath in this.GetResolvedProviderPathFromPSPath(path, out provider))
                        {
                            if (!Directory.Exists(expandedFilePath))
                            {
                                filePaths.Add(expandedFilePath);
                            }
                        }
                    }
                    else
                    {
                        // no wildcards, so don't try to expand any * or ? symbols.
                        filePaths.Add(this.SessionState.Path.GetUnresolvedProviderPathFromPSPath(path, out provider, out drive));
                    }
                    // ensure that this path (or set of paths after wildcard expansion)
                    // is on the filesystem. A wildcard can never expand to span multiple providers.
                    if (Common.IsFileSystemPath(provider, path) == false)
                    {
                        // no, so skip to next path in paths.
                        continue;
                    }
                }

                // At this point, we have a list of paths on the filesystem, send each file to the remote endpoint
                foreach (string filePath in filePaths)
                {
                    System.Diagnostics.Stopwatch timer = new System.Diagnostics.Stopwatch();

                    // confirm the file exists
                    if (!File.Exists(filePath))
                    {
                        FileNotFoundException fileException     = new FileNotFoundException("File not found", filePath);
                        ErrorRecord           fileNotFoundError = new ErrorRecord(fileException, "FileNotFound", ErrorCategory.ObjectNotFound, filePath);
                        WriteError(fileNotFoundError);
                        return;
                    }

                    // send the file to the endpoint using MLLP framing
                    TcpClient tcpConnection = new TcpClient();
                    tcpConnection.SendTimeout    = 10000;
                    tcpConnection.ReceiveTimeout = 10000;
                    try {
                        // get the contents of the file
                        string fileContents = File.ReadAllText(filePath);

                        // save the string as a HL7Message, this will validate the file is a HL7 v2 message.
                        HL7Message message = new HL7Message(fileContents);
                        WriteVerbose("Connecting to " + this.hostname + ":" + this.port);

                        // create a TCP socket connection to the reciever, start timing the elapsed time to deliver the message and receive the ACK
                        timer.Start();
                        tcpConnection.Connect(this.hostname, this.port);
                        NetworkStream tcpStream   = tcpConnection.GetStream();
                        UTF8Encoding  encoder     = new UTF8Encoding();
                        Byte[]        writeBuffer = new Byte[4096];

                        // get the message text with MLLP framing
                        writeBuffer = encoder.GetBytes(message.GetMLLPFramedMessage());
                        tcpStream.Write(writeBuffer, 0, writeBuffer.Length);
                        tcpStream.Flush();
                        WriteVerbose("Message sent");

                        // wait for ack unless the -NoACK switch was set
                        string[] ackLines = null;
                        if (!this.noACK)
                        {
                            WriteVerbose("Waiting for ACK ...");
                            Byte[] readBuffer = new Byte[4096];
                            int    bytesRead  = tcpStream.Read(readBuffer, 0, 4096);
                            string ackMessage = encoder.GetString(readBuffer, 0, bytesRead);
                            // look for the start of the MLLP frame (VT control character)
                            int start = ackMessage.IndexOf((char)0x0B);
                            if (start >= 0)
                            {
                                // Search for the end of the MLLP frame (FS control character)
                                int end = ackMessage.IndexOf((char)0x1C);
                                if (end > start)
                                {
                                    // split the ACK message on <CR> character (segment delineter), output each segment of the ACK on a new line
                                    // remove the last <CR> character if present, otherwise the final element in the array will be empty when splitting the string
                                    string ackString = ackMessage.Substring(start + 1, end - 1);
                                    if (ackString[ackString.Length - 1] == (char)0x0D)
                                    {
                                        ackString = ackString.Substring(0, ackString.Length - 1);
                                    }
                                    ackLines = ackString.Split((char)0x0D);
                                }
                            }
                        }

                        // stop timing the operation, output the result object
                        timer.Stop();
                        SendHL7MessageResult result = new SendHL7MessageResult("Successful", ackLines, DateTime.Now, message.ToString().Split((char)0x0D), this.hostname, this.port, filePath, timer.Elapsed.TotalMilliseconds / 1000);
                        WriteObject(result);
                        WriteVerbose("Closing TCP session\n");
                        tcpStream.Close();
                    }
                    // if the file does not start with a MSH segment, the constructor will throw an exception.
                    catch (ArgumentException) {
                        ArgumentException argException      = new ArgumentException("The file does not appear to be a valid HL7 v2 message", filePath);
                        ErrorRecord       fileNotFoundError = new ErrorRecord(argException, "FileNotValid", ErrorCategory.InvalidData, filePath);
                        WriteError(fileNotFoundError);
                        return;
                    }
                    // catch failed TCP connections
                    catch (SocketException se) {
                        ErrorRecord SocketError = new ErrorRecord(se, "ConnectionError", ErrorCategory.ConnectionError, this.hostname + ":" + this.port);
                        WriteError(SocketError);
                        return;
                    }
                    finally {
                        tcpConnection.Close();
                    }

                    // delay between sending messages
                    if (this.delayBetweenMessages > 0)
                    {
                        System.Threading.Thread.Sleep(this.delayBetweenMessages * 1000);
                    }
                }
            }
        }
        /// <summary>
        /// get the HL7 item provided via the cmdlet parameter HL7ItemPosition
        /// </summary>
        protected override void ProcessRecord()
        {
            // confirm the item location parameter is valid before processing any files
            if (!Common.IsHL7LocationStringValid(this.itemPosition))
            {
                ArgumentException ex    = new ArgumentException(this.itemPosition + " does not appear to be a valid HL7 item");
                ErrorRecord       error = new ErrorRecord(ex, "InvalidElement", ErrorCategory.InvalidArgument, this.itemPosition);
                this.WriteError(error);
                return;
            }

            // confirm the filter parameter is valid before processing any files
            foreach (string currentFilter in this.filter)
            {
                // confirm each filter is formatted correctly
                if (!Common.IsFilterValid(currentFilter))
                {
                    ArgumentException ex    = new ArgumentException(currentFilter + " does not appear to be a valid filter");
                    ErrorRecord       error = new ErrorRecord(ex, "InvalidFilter", ErrorCategory.InvalidArgument, currentFilter);
                    this.WriteError(error);
                    return;
                }
            }

            // set the text encoding
            Encoding encoder = System.Text.Encoding.GetEncoding(this.encoding);

            WriteVerbose("Encoding: " + encoder.EncodingName);

            // expand the file or directory information provided in the -Path or -LiteralPath parameters
            foreach (string path in paths)
            {
                // This will hold information about the provider containing the items that this path string might resolve to.
                ProviderInfo provider;

                // This will be used by the method that processes literal paths
                PSDriveInfo drive;

                // this contains the paths to process for this iteration of the loop to resolve and optionally expand wildcards.
                List <string> filePaths = new List <string>();

                // if the path provided is a directory, expand the files in the directy and add these to the list.
                if (Directory.Exists(path))
                {
                    filePaths.AddRange(Directory.GetFiles(path));
                }

                // not a directory, could be a wildcard or literal filepath
                else
                {
                    // expand wildcards. This assumes if the user listed a directory it is literal
                    if (expandWildcards)
                    {
                        // Turn *.txt into foo.txt,foo2.txt etc. If path is just "foo.txt," it will return unchanged. If the filepath expands into a directory ignore it.
                        foreach (string expandedFilePath in this.GetResolvedProviderPathFromPSPath(path, out provider))
                        {
                            if (!Directory.Exists(expandedFilePath))
                            {
                                filePaths.Add(expandedFilePath);
                            }
                        }
                    }
                    else
                    {
                        // no wildcards, so don't try to expand any * or ? symbols.
                        filePaths.Add(this.SessionState.Path.GetUnresolvedProviderPathFromPSPath(path, out provider, out drive));
                    }
                    // ensure that this path (or set of paths after wildcard expansion)
                    // is on the filesystem. A wildcard can never expand to span multiple providers.
                    if (Common.IsFileSystemPath(provider, path) == false)
                    {
                        // no, so skip to next path in paths.
                        continue;
                    }
                }

                // At this point, we have a list of paths on the filesystem, process each file.
                foreach (string filePath in filePaths)
                {
                    // If the file does not exist display an error and return.
                    if (!File.Exists(filePath))
                    {
                        FileNotFoundException fileException     = new FileNotFoundException("File not found", filePath);
                        ErrorRecord           fileNotFoundError = new ErrorRecord(fileException, "FileNotFound", ErrorCategory.ObjectNotFound, filePath);
                        WriteError(fileNotFoundError);
                        return;
                    }

                    // if the ItemPosition parameter is not in the correct format display an error and return
                    if (!Common.IsItemLocationValid(this.itemPosition))
                    {
                        ArgumentException argException   = new ArgumentException("The -ItemPosition parameter does not appear to be in the correct format.", this.itemPosition);
                        ErrorRecord       parameterError = new ErrorRecord(argException, "ParameterNotValid", ErrorCategory.InvalidArgument, this.itemPosition);
                        WriteError(parameterError);
                        return;
                    }

                    // process the message
                    try {
                        // assume the filter is true, until a failed match is found
                        this.filterConditionsMet = true;
                        // load the file into a HL7Message object for processing
                        string     fileContents = File.ReadAllText(filePath, encoder);
                        HL7Message message      = new HL7Message(fileContents);
                        // if a filter was supplied, evaluate if the file matches the filter condition
                        if (this.filter != null)
                        {
                            // check to see is all of the filter conditions are met (ie AND all filters supplied).
                            foreach (string currentFilter in this.filter)
                            {
                                bool   anyItemMatch = false;
                                string filterItem   = Common.GetFilterItem(currentFilter);
                                string filterValue  = Common.GetFilterValue(currentFilter);
                                // for repeating fields, only one of the items returned has to match for the filter to be evaluated as true.
                                foreach (string itemValue in message.GetHL7ItemValue(filterItem))
                                {
                                    if (itemValue.ToUpper() == filterValue.ToUpper())
                                    {
                                        anyItemMatch = true;
                                    }
                                }
                                // if none of the repeating field items match, then fail the filter match for this file.
                                if (!anyItemMatch)
                                {
                                    this.filterConditionsMet = false;
                                }
                            }
                        }

                        // if the filter supplied matches this message (or no filter provided) then process the file to optain the HL7 item requested
                        if (filterConditionsMet)
                        {
                            List <HL7Item> hl7Items = message.GetHL7Item(itemPosition);
                            // if the hl7Items array is  empty, the item was not found in the message
                            if (hl7Items.Count == 0)
                            {
                                WriteWarning("Item " + this.itemPosition + " not found in the message " + filePath);
                            }

                            //  items were located in the message, so proceed with replacing the original value with the new value.
                            else
                            {
                                // update all repeats/occurances of the specified item
                                if (this.allrepeats)
                                {
                                    foreach (HL7Item item in hl7Items)
                                    {
                                        // appeand the new value to the existing value of the item if -AppendToExistingValue switch is set
                                        if (appendValue)
                                        {
                                            this.newValue = item.ToString() + this.newValue;
                                        }
                                        // update the item value
                                        SetHL7ItemResult result = new SetHL7ItemResult(this.newValue, item.ToString(), filePath, this.itemPosition);
                                        item.SetValueFromString(this.newValue);
                                        WriteObject(result);
                                    }
                                }
                                // update only the first occurrance. This is the default action.
                                else
                                {
                                    // append the new value to the existing value of the item if -AppendToExistingValue switch is set
                                    if (appendValue)
                                    {
                                        this.newValue = hl7Items.ElementAt(0).ToString() + this.newValue;
                                    }
                                    // update the item value
                                    SetHL7ItemResult result = new SetHL7ItemResult(this.newValue, hl7Items.ElementAt(0).ToString(), filePath, this.itemPosition);
                                    hl7Items.ElementAt(0).SetValueFromString(this.newValue);
                                    WriteObject(result);
                                }
                                // Write changes to the file. Replace the segment delimeter <CR> with the system newline string as this is being written to a file.
                                string cr      = ((char)0x0D).ToString();
                                string newline = System.Environment.NewLine;
                                if (this.ShouldProcess(filePath, "Saving changes to file"))
                                {
                                    System.IO.File.WriteAllText(filePath, message.ToString().Replace(cr, newline), encoder);
                                }
                            }
                        }
                    }

                    // if the file does not start with a MSH segment, the constructor will throw an exception.
                    catch (System.ArgumentException) {
                        ArgumentException argException     = new ArgumentException("The file does not appear to be a valid HL7 v2 message", filePath);
                        ErrorRecord       invalidFileError = new ErrorRecord(argException, "FileNotValid", ErrorCategory.InvalidData, filePath);
                        WriteError(invalidFileError);
                        return;
                    }
                }
            }
        }
Example #5
0
        /// <summary>
        /// Receive data from a client connection, look for MLLP HL7 message.
        /// </summary>
        /// <param name="client"></param>
        private void ReceiveData(object client)
        {
            // generate a random sequence number to use for the file names
            Random random = new Random(Guid.NewGuid().GetHashCode());
            int    filenameSequenceStart = random.Next(0, 1000000);

            TcpClient     tcpClient    = (TcpClient)client;
            NetworkStream clientStream = tcpClient.GetStream();

            clientStream.ReadTimeout  = TCP_TIMEOUT;
            clientStream.WriteTimeout = TCP_TIMEOUT;

            byte[] messageBuffer = new byte[4096];
            int    bytesRead;
            String messageData  = "";
            int    messageCount = 0;

            while (true)
            {
                bytesRead = 0;
                try {
                    // Wait until a client application submits a message
                    bytesRead = clientStream.Read(messageBuffer, 0, 4096);
                }
                catch (Exception) {
                    // A network error has occurred
                    LogDebug("Connection from " + tcpClient.Client.RemoteEndPoint + " has ended");
                    break;
                }
                if (bytesRead == 0)
                {
                    // The client has disconected
                    LogDebug("The client " + tcpClient.Client.RemoteEndPoint + " has disconnected");
                    break;
                }
                // Message buffer received successfully
                messageData += Encoding.UTF8.GetString(messageBuffer, 0, bytesRead);
                // Find a VT character, this is the beginning of the MLLP frame
                int start = messageData.IndexOf((char)0x0B);
                if (start >= 0)
                {
                    // Search for the end of the MLLP frame (a FS character)
                    int end = messageData.IndexOf((char)0x1C);
                    if (end > start)
                    {
                        messageCount++;
                        try {
                            // queue the message to sent to the passthru host if the -PassThru option has been set
                            if (passthruHost != null)
                            {
                                messageQueue.Enqueue(messageData.Substring(start + 1, end - (start + 1)));
                            }
                            // create a HL7message object from the message recieved. Use this to access elements needed to populate the ACK message and file name of the archived message
                            HL7Message message = new HL7Message(messageData.Substring(start + 1, end - (start + 1)));
                            messageData = ""; // reset the message data string for the next message
                            string messageTrigger   = message.GetHL7ItemValue("MSH-9")[0];
                            string messageControlID = message.GetHL7ItemValue("MSH-10")[0];
                            //string acceptAckType = message.GetHL7Item("MSH-15")[0];
                            string dateStamp = DateTime.Now.Year.ToString() + DateTime.Now.Month.ToString().PadLeft(2, '0') + DateTime.Now.Day.ToString().PadLeft(2, '0') + DateTime.Now.Hour.ToString().PadLeft(2, '0') + DateTime.Now.Minute.ToString().PadLeft(2, '0');
                            string filename  = dateStamp + "_" + (filenameSequenceStart + messageCount).ToString("D6") + "_" + messageTrigger + ".hl7"; //  increment sequence number for each filename
                            // Write the HL7 message to file.
                            WriteMessagetoFile(message.ToString(), System.IO.Path.Combine(this.archivePath, filename));
                            ReceivedMessageResult resultObject = new ReceivedMessageResult(messageTrigger, System.IO.Path.Combine(this.archivePath, filename), tcpClient.Client.RemoteEndPoint.ToString());
                            objectQueue.Enqueue(resultObject);
                            // send ACK message is MSH-15 is set to AL and ACKs not disbaled by -NOACK command line switch
                            //if ((this.sendACK) && (acceptAckType.ToUpper() == "AL"))
                            if (this.sendACK)
                            {
                                LogDebug("Sending ACK (Message Control ID: " + messageControlID + ")");
                                // generate ACK Message and send in response to the message received
                                string response        = GenerateACK(message.ToString()); // TO DO: send ACKS if set in message header, or specified on command line
                                byte[] encodedResponse = Encoding.UTF8.GetBytes(response);
                                // Send response
                                try {
                                    clientStream.Write(encodedResponse, 0, encodedResponse.Length);
                                    clientStream.Flush();
                                }
                                catch (Exception e) {
                                    // A network error has occurred
                                    LogDebug("An error has occurred while sending an ACK to the client " + tcpClient.Client.RemoteEndPoint);
                                    LogDebug(e.Message);
                                    break;
                                }
                            }
                        }
                        catch (Exception e) {
                            messageData = ""; // reset the message data string for the next message
                            LogWarning("An exception occurred while parsing the HL7 message");
                            LogWarning(e.Message);
                            break;
                        }
                    }
                }
            }
            LogDebug("Total messages received:" + messageCount);
            clientStream.Close();
            clientStream.Dispose();
            tcpClient.Close();
        }
Example #6
0
        /// <summary>
        /// get the HL7 item provided via the cmdlet parameter HL7ItemPosition
        /// </summary>
        protected override void ProcessRecord()
        {
            // confirm the item location parameter is valid before processing any files
            if (!Common.IsHL7LocationStringValid(this.itemPosition))
            {
                ArgumentException ex    = new ArgumentException(this.itemPosition + " does not appear to be a valid HL7 item");
                ErrorRecord       error = new ErrorRecord(ex, "InvalidElement", ErrorCategory.InvalidArgument, this.itemPosition);
                this.WriteError(error);
                return;
            }

            // confirm the filter parameter is valid before processing any files
            foreach (string currentFilter in this.filter)
            {
                // confirm each filter is formatted correctly
                if (!Common.IsFilterValid(currentFilter))
                {
                    ArgumentException ex    = new ArgumentException(currentFilter + " does not appear to be a valid filter");
                    ErrorRecord       error = new ErrorRecord(ex, "InvalidFilter", ErrorCategory.InvalidArgument, currentFilter);
                    this.WriteError(error);
                    return;
                }
            }

            // expand the file or directory information provided in the -Path or -LiteralPath parameters
            foreach (string path in paths)
            {
                // This will hold information about the provider containing the items that this path string might resolve to.
                ProviderInfo provider;

                // This will be used by the method that processes literal paths
                PSDriveInfo drive;

                // this contains the paths to process for this iteration of the loop to resolve and optionally expand wildcards.
                List <string> filePaths = new List <string>();

                // if the path provided is a directory, expand the files in the directy and add these to the list.
                if (Directory.Exists(path))
                {
                    filePaths.AddRange(Directory.GetFiles(path));
                }

                // not a directory, could be a wildcard or literal filepath
                else
                {
                    // expand wildcards. This assumes if the user listed a directory it is literal
                    if (expandWildcards)
                    {
                        // Turn *.txt into foo.txt,foo2.txt etc. If path is just "foo.txt," it will return unchanged. If the filepath expands into a directory ignore it.
                        foreach (string expandedFilePath in this.GetResolvedProviderPathFromPSPath(path, out provider))
                        {
                            if (!Directory.Exists(expandedFilePath))
                            {
                                filePaths.Add(expandedFilePath);
                            }
                        }
                    }
                    else
                    {
                        // no wildcards, so don't try to expand any * or ? symbols.
                        filePaths.Add(this.SessionState.Path.GetUnresolvedProviderPathFromPSPath(path, out provider, out drive));
                    }
                    // ensure that this path (or set of paths after wildcard expansion)
                    // is on the filesystem. A wildcard can never expand to span multiple providers.
                    if (Common.IsFileSystemPath(provider, path) == false)
                    {
                        // no, so skip to next path in paths.
                        continue;
                    }
                }

                // At this point, we have a list of paths on the filesystem, process each file.
                foreach (string filePath in filePaths)
                {
                    // If the file does not exist display an error and return.
                    if (!File.Exists(filePath))
                    {
                        FileNotFoundException fileException     = new FileNotFoundException("File not found", filePath);
                        ErrorRecord           fileNotFoundError = new ErrorRecord(fileException, "FileNotFound", ErrorCategory.ObjectNotFound, filePath);
                        WriteError(fileNotFoundError);
                        return;
                    }

                    // if the ItemPosition parameter is not in the correct format display an error and return
                    if (!Common.IsItemLocationValid(this.itemPosition))
                    {
                        ArgumentException argException   = new ArgumentException("The -ItemPosition parameter does not appear to be in the correct format.", this.itemPosition);
                        ErrorRecord       parameterError = new ErrorRecord(argException, "ParameterNotValid", ErrorCategory.InvalidArgument, this.itemPosition);
                        WriteError(parameterError);
                        return;
                    }

                    // process the message
                    try {
                        // assume the filter is true, until a failed match is found
                        this.filterConditionsMet = true;
                        // load the file into a HL7Message object for processing
                        string     fileContents = File.ReadAllText(filePath);
                        HL7Message message      = new HL7Message(fileContents);
                        // if a filter was supplied, evaluate if the file matches the filter condition
                        if (this.filter != null)
                        {
                            // check to see is all of the filter conditions are met (ie AND all filters supplied).
                            foreach (string currentFilter in this.filter)
                            {
                                bool   anyItemMatch = false;
                                string filterItem   = Common.GetFilterItem(currentFilter);
                                string filterValue  = Common.GetFilterValue(currentFilter);
                                // for repeating fields, only one of the items returned has to match for the filter to be evaluated as true.
                                foreach (string itemValue in message.GetHL7ItemValue(filterItem))
                                {
                                    // convert both values to upper case for a case insentive match
                                    if (itemValue.ToUpper() == filterValue.ToUpper())
                                    {
                                        anyItemMatch = true;
                                    }
                                }
                                // if none of the repeating field items match, then fail the filter match for this file.
                                if (!anyItemMatch)
                                {
                                    this.filterConditionsMet = false;
                                }
                            }
                        }

                        // if the filter supplied matches this message (or no filter provided) then process the file to optain the HL7 item requested
                        if (filterConditionsMet)
                        {
                            string[] hl7Items = message.GetHL7ItemValue(itemPosition);
                            // if the hl7Items array is  empty, the item was not found in the message
                            if (hl7Items.Length == 0)
                            {
                                WriteWarning("Item " + this.itemPosition + " not found in the message " + filePath);
                            }

                            //  items were returned
                            else
                            {
                                SelectHL7ItemResult result = new SelectHL7ItemResult(hl7Items, filePath);
                                WriteObject(result);
                            }
                        }
                    }

                    // if the file does not start with a MSH segment, the constructor will throw an exception.
                    catch (System.ArgumentException) {
                        ArgumentException argException     = new ArgumentException("The file does not appear to be a valid HL7 v2 message", filePath);
                        ErrorRecord       invalidFileError = new ErrorRecord(argException, "FileNotValid", ErrorCategory.InvalidData, filePath);
                        WriteError(invalidFileError);
                        return;
                    }
                }
            }
        }
Example #7
0
        /// <summary>
        /// remove identifying fields
        /// </summary>
        protected override void ProcessRecord()
        {
            // validate the that the list of locations to mask is valid.
            foreach (string item in this.customItemsList)
            {
                // confirm each filter is formatted correctly
                if (!Common.IsItemLocationValid(item))
                {
                    ArgumentException ex    = new ArgumentException(item + " does not appear to be a valid HL7 location");
                    ErrorRecord       error = new ErrorRecord(ex, "InvalidFilter", ErrorCategory.InvalidArgument, item);
                    this.WriteError(error);
                    return;
                }
            }

            // set the text encoding
            Encoding encoder = System.Text.Encoding.GetEncoding(this.encoding);

            WriteVerbose("Encoding: " + encoder.EncodingName);

            foreach (string path in paths)
            {
                // This will hold information about the provider containing the items that this path string might resolve to.
                ProviderInfo provider;

                // This will be used by the method that processes literal paths
                PSDriveInfo drive;

                // this contains the paths to process for this iteration of the loop to resolve and optionally expand wildcards.
                List <string> filePaths = new List <string>();

                // if the path provided is a directory, expand the files in the directory and add these to the list.
                if (Directory.Exists(path))
                {
                    filePaths.AddRange(Directory.GetFiles(path));
                }

                // not a directory, could be a wild-card or literal filepath
                else
                {
                    if (expandWildcards)
                    {
                        // Turn *.txt into foo.txt,foo2.txt etc. If path is just "foo.txt," it will return unchanged. If the filepath expands into a directory ignore it.
                        foreach (string expandedFilePath in this.GetResolvedProviderPathFromPSPath(path, out provider))
                        {
                            if (!Directory.Exists(expandedFilePath))
                            {
                                filePaths.Add(expandedFilePath);
                            }
                        }
                    }
                    else
                    {
                        // no wildcards, so don't try to expand any * or ? symbols.
                        filePaths.Add(this.SessionState.Path.GetUnresolvedProviderPathFromPSPath(path, out provider, out drive));
                    }
                    // ensure that this path (or set of paths after wildcard expansion)
                    // is on the filesystem. A wildcard can never expand to span multiple providers.
                    if (Common.IsFileSystemPath(provider, path) == false)
                    {
                        // no, so skip to next path in paths.
                        continue;
                    }
                }

                // At this point, we have a list of paths on the filesystem, process each file.
                foreach (string filePath in filePaths)
                {
                    // If the file does not exist display an error and return.
                    if (!File.Exists(filePath))
                    {
                        FileNotFoundException fileException     = new FileNotFoundException("File not found", filePath);
                        ErrorRecord           fileNotFoundError = new ErrorRecord(fileException, "FileNotFound", ErrorCategory.ObjectNotFound, filePath);
                        WriteError(fileNotFoundError);
                        return;
                    }
                    try {
                        string     fileContents = File.ReadAllText(filePath, encoder);
                        HL7Message message      = new HL7Message(fileContents);
                        // if a custom list of items is provided, then mask out each nominated item
                        if (customItemsList.Length > 0)
                        {
                            foreach (string item in customItemsList)
                            {
                                message.MaskHL7Item(item, this.maskChar);
                            }
                        }

                        // otherwise mask out default items
                        else
                        {
                            message.DeIdentify(this.maskChar);
                        }

                        char   pathSeparator = System.IO.Path.DirectorySeparatorChar;
                        string newFilename   = filePath.Substring(0, filePath.LastIndexOf(pathSeparator) + 1) + "MASKED_" + filePath.Substring(filePath.LastIndexOf(pathSeparator) + 1, filePath.Length - (filePath.LastIndexOf(pathSeparator) + 1));

                        // if the overwrite switch is set, then use the original file name.
                        if (this.overwriteFile)
                        {
                            newFilename = filePath;
                        }
                        // Write changes to the file. Replace the segment delimeter <CR> with the system newline string as this is being written to a file.
                        string cr      = ((char)0x0D).ToString();
                        string newline = System.Environment.NewLine;
                        if (this.ShouldProcess(newFilename, "Saving changes to file"))
                        {
                            System.IO.File.WriteAllText(newFilename, message.ToString().Replace(cr, newline), encoder);
                        }
                        WriteObject("Masked file saved as " + newFilename);
                    }

                    // if the file does not start with a MSH segment, the constructor will throw an exception.
                    catch (System.ArgumentException) {
                        ArgumentException argException      = new ArgumentException("The file does not appear to be a valid HL7 v2 message", filePath);
                        ErrorRecord       fileNotFoundError = new ErrorRecord(argException, "FileNotValid", ErrorCategory.InvalidData, filePath);
                        WriteError(fileNotFoundError);
                        return;
                    }
                }
            }
        }
Example #8
0
        /// <summary>
        /// get the HL7 item provided via the cmdlet parameter HL7ItemPosition
        /// </summary>
        protected override void ProcessRecord()
        {
            // expand the file or directory information provided in the -Path or -LiteralPath parameters
            foreach (string path in paths)
            {
                // This will hold information about the provider containing the items that this path string might resolve to.
                ProviderInfo provider;
                // This will be used by the method that processes literal paths
                PSDriveInfo drive;
                // this contains the paths to process for this iteration of the loop to resolve and optionally expand wildcards.
                List <string> filePaths = new List <string>();

                // if the path provided is a directory, expand the files in the directory and add these to the list.
                if (Directory.Exists(path))
                {
                    filePaths.AddRange(Directory.GetFiles(path));
                }

                // not a directory, could be a wildcard or literal filepath
                else
                {
                    // expand wildcards. This assumes if the user listed a directory it is literal
                    if (expandWildcards)
                    {
                        // Turn *.txt into foo.txt,foo2.txt etc. If path is just "foo.txt," it will return unchanged. If the filepath expands into a directory ignore it.
                        foreach (string expandedFilePath in this.GetResolvedProviderPathFromPSPath(path, out provider))
                        {
                            if (!Directory.Exists(expandedFilePath))
                            {
                                filePaths.Add(expandedFilePath);
                            }
                        }
                    }
                    else
                    {
                        // no wildcards, so don't try to expand any * or ? symbols.
                        filePaths.Add(this.SessionState.Path.GetUnresolvedProviderPathFromPSPath(path, out provider, out drive));
                    }
                    // ensure that this path (or set of paths after wildcard expansion)
                    // is on the filesystem. A wildcard can never expand to span multiple providers.
                    if (Common.IsFileSystemPath(provider, path) == false)
                    {
                        // no, so skip to next path in paths.
                        continue;
                    }
                }

                // At this point, we have a list of paths on the filesystem, process each file.
                foreach (string filePath in filePaths)
                {
                    // If the file does not exist display an error and return.
                    if (!File.Exists(filePath))
                    {
                        FileNotFoundException fileException     = new FileNotFoundException("File not found", filePath);
                        ErrorRecord           fileNotFoundError = new ErrorRecord(fileException, "FileNotFound", ErrorCategory.ObjectNotFound, filePath);
                        WriteError(fileNotFoundError);
                        return;
                    }

                    // process the message
                    try {
                        // load the file into a HL7Message object for processing
                        string     fileContents = File.ReadAllText(filePath);
                        HL7Message message      = new HL7Message(fileContents);

                        // get the message trigger from MSH-9 (only interested in MSH-9.1 and MSH-9.2 - ignore any document types if included).
                        string[] messageTrigger = message.GetHL7ItemValue("MSH-9");
                        string[] splitTrigger   = messageTrigger[0].Split(message.ComponentDelimeter);
                        string   simplifiedTrigger;
                        if (splitTrigger.Length > 1)
                        {
                            simplifiedTrigger = splitTrigger[0] + message.ComponentDelimeter + splitTrigger[1];
                        }
                        else
                        {
                            simplifiedTrigger = splitTrigger[0];
                        }

                        // get the message timestamp
                        string[] messageDateTime = message.GetHL7ItemValue("MSH-7");
                        // if the hl7Items array is  empty, the item was not found in the message
                        if (messageDateTime.Length == 0)
                        {
                            WriteWarning("MSH-7 does not contain a value for " + filePath);
                        }
                        //  items were returned
                        else
                        {
                            string timePattern     = "[0-9]{12}([0-9]{2})?";
                            string timezonePattern = "(?<=(/+|-))[0-9]{4}";

                            Match timeMatch     = Regex.Match(messageDateTime[0], timePattern);
                            Match timezoneMatch = Regex.Match(messageDateTime[0], timezonePattern);

                            if (timeMatch.Success)
                            {
                                // time zone is includes
                                if (timezoneMatch.Success)
                                {
                                    // time includes seconds
                                    if (timeMatch.Value.Length == 14)
                                    {
                                        ShowHL7MessageTimelineResult resultListItem = new ShowHL7MessageTimelineResult(DateTime.ParseExact(timeMatch.Value + timezoneMatch.Groups[1].Value + timezoneMatch.Value, "yyyyMMddHHmmsszzzz", null), filePath, simplifiedTrigger);
                                        messageTimestampResults.Add(resultListItem);
                                    }
                                    // time only resolves to minutes
                                    else
                                    {
                                        ShowHL7MessageTimelineResult resultListItem = new ShowHL7MessageTimelineResult(DateTime.ParseExact(timeMatch.Value + timezoneMatch.Groups[1].Value + timezoneMatch.Value, "yyyyMMddHHmmzzzz", null), filePath, simplifiedTrigger);
                                        messageTimestampResults.Add(resultListItem);
                                    }
                                }
                                // timezone is not included
                                else
                                {
                                    // time includes seconds
                                    if (timeMatch.Value.Length == 14)
                                    {
                                        ShowHL7MessageTimelineResult resultListItem = new ShowHL7MessageTimelineResult(DateTime.ParseExact(timeMatch.Value, "yyyyMMddHHmmss", null), filePath, simplifiedTrigger);
                                        messageTimestampResults.Add(resultListItem);
                                    }
                                    // time only resolves to minutes
                                    else
                                    {
                                        ShowHL7MessageTimelineResult resultListItem = new ShowHL7MessageTimelineResult(DateTime.ParseExact(timeMatch.Value, "yyyyMMddHHmm", null), filePath, simplifiedTrigger);
                                        messageTimestampResults.Add(resultListItem);
                                    }
                                }
                            }
                            // timestamp missing, or does not resolve down to at least minutes
                            else
                            {
                                WriteWarning("Timestamp missing from " + filePath);
                            }
                        }
                    }
                    // if the file does not start with a MSH segment, the constructor will throw an exception.
                    catch (System.ArgumentException) {
                        ArgumentException argException     = new ArgumentException("The file does not appear to be a valid HL7 v2 message", filePath);
                        ErrorRecord       invalidFileError = new ErrorRecord(argException, "FileNotValid", ErrorCategory.InvalidData, filePath);
                        WriteError(invalidFileError);
                        return;
                    }
                }
            }
        }