Beispiel #1
0
        internal static void Encode(HL7Separators seps, System.Text.StringBuilder sb, Type type, object value)
        {
            if (value == null)
            {
                // Do nothing
            }
            else if (type.IsArray)
            {
                foreach (object element in value as Array)
                {
                    Encode(seps, sb, type.GetElementType(), element);
                    sb.Append(seps.FieldRepeatSeparator);
                }

                // Remove the last field repeat separator.
                sb.Remove(sb.Length - 1, 1);
            }
            else if (type.Equals(typeof(string)))
            {
                sb.Append(seps.Encode(value as string));
            }
            else
            {
                foreach (FieldInfo component in type.GetFields())
                {
                    HL7Component.Encode(seps, sb, component.FieldType, component.GetValue(value));
                    sb.Append(seps.ComponentSeparator);
                }

                // Remove the last component separator.
                sb.Remove(sb.Length - 1, 1);
            }
        }
Beispiel #2
0
        internal void Encode(HL7Separators seps, System.Text.StringBuilder sb)
        {
            FieldInfo[] fields = GetType().GetFields();

            sb.Append(GetType().Name);
            sb.Append(seps.FieldSeparator);

            foreach (FieldInfo field in fields)
            {
                if (this is MSH && field.Name.Equals("FieldSeparator"))
                {
                    // A field separator was already added after the segment HL7Name, don't add another.
                }
                else if (this is MSH && field.Name.Equals("EncodingCharacters"))
                {
                    // We want the encoding characters raw, not escaped.
                    sb.Append(field.GetValue(this));
                    sb.Append(seps.FieldSeparator);
                }
                else
                {
                    HL7Field.Encode(seps, sb, field.FieldType, field.GetValue(this));
                    sb.Append(seps.FieldSeparator);
                }
            }
        }
Beispiel #3
0
        /// <summary>
        /// Encode message according to HL7 encoding rules with specified separators.
        /// </summary>
        /// <param HL7Name="seps">Characters to separate segments, fields, field repeats, components and subcomponents</param>
        /// <returns>Bytes for HL7 message</returns>
        public string Encode(HL7Separators seps)
        {
            StringBuilder sb = new StringBuilder();

            // Encode this full message as a segment group
            base.Encode(seps, sb);

            return(Cleanup(seps, sb.ToString()));
        }
Beispiel #4
0
        /// <summary>
        /// Parses the received HL7 message.
        /// </summary>
        /// <param name="messageForm">The raw message encoded in HL7 'pipes and hats' format.</param>
        /// <returns>The parsed HL7 message object</returns>
        /// <exception cref="HL7ParseException">Thrown when parsing fails</exception>
        public static HL7Message Parse(string messageForm)
        {
            // Determine the HL7 separators dynamically from the incoming message (usually "|^~\&")
            HL7Separators sep = new HL7Separators(messageForm);

            // Change CRLF or LF into the standard CR separators
            if (messageForm.Contains("\r\n"))
            {
                messageForm = messageForm.Replace("\r\n", "\r");
            }
            if (messageForm.Contains("\n"))
            {
                messageForm = messageForm.Replace("\n", "\r");
            }

            // Remove consecutive segment separators
            while (messageForm.Contains("\r\r"))
            {
                messageForm = messageForm.Replace("\r\r", "\r");
            }

            // Parse all the segments
            messageForm = messageForm.TrimEnd(new char[] { sep.SegmentSeparator });
            string[] segmentForm = messageForm.Split(sep.SegmentSeparator);
            for (int count = 0; count < segmentForm.Count(); count++)
            {
                segmentForm[count] = segmentForm[count].Replace("\n", string.Empty);
            }
            HL7Segment[] segments = new HL7Segment[segmentForm.Length];
            for (int i = 0; i < segmentForm.Length; i++)
            {
                segments[i] = HL7Segment.Parse(segmentForm[i], sep);
            }

            // Grab the MSH segment in order to determine which message structure to use
            MSH msh = segments[0] as MSH;

            if (msh == null)
            {
                throw new HL7ParseException(ConstantsResource.HL7NoMshSegment);
            }
            if (msh.MessageType == null)
            {
                throw new HL7ParseException(ConstantsResource.NoMessageType);
            }

            // Determine the structure for the indicated message identifier
            Type messageStructure = GetMessageStructure(msh.MessageType);

            // Create the message and populate all the matching segments into its structure
            int        segmentIndex = 0;
            HL7Message message      = BuildSegmentGroup(messageStructure, segments, ref segmentIndex) as HL7Message;

            return(message);
        }
Beispiel #5
0
        /// <summary>
        /// Encode segment group according to HL7 encoding rules with specified separators.
        /// </summary>
        /// <param HL7Name="seps">Characters to separate segments, fields, field repeats, components and subcomponents</param>
        /// <param HL7Name="sb">String builder</param>
        public void Encode(HL7Separators seps, StringBuilder sb)
        {
            var segmentGroupFields = GetType().GetFields().OrderBy(f => f.MetadataToken);

            foreach (FieldInfo segmentGroupField in segmentGroupFields)
            {
                if (segmentGroupField.FieldType.IsArray)
                {
                    Array array = segmentGroupField.GetValue(this) as Array;
                    foreach (object segmentGroupObject in array)
                    {
                        // Each item in the array could be another group of segments or a single segment

                        if (segmentGroupObject is HL7SegmentGroup)
                        {
                            HL7SegmentGroup segmentGroup = segmentGroupObject as HL7SegmentGroup;
                            segmentGroup.Encode(seps, sb);
                        }
                        else
                        {
                            HL7Segment segment = segmentGroupObject as HL7Segment;
                            segment.Encode(seps, sb);
                            sb.Append(seps.SegmentSeparator);
                        }
                    }
                }
                else
                {
                    // The non-repeating item could be a another group of segments, or a single segment, or null

                    object segmentGroupObject = segmentGroupField.GetValue(this);
                    if (segmentGroupObject is HL7SegmentGroup)
                    {
                        HL7SegmentGroup segmentGroup = segmentGroupObject as HL7SegmentGroup;
                        segmentGroup.Encode(seps, sb);
                    }
                    else if (segmentGroupObject != null)
                    {
                        HL7Segment segment = segmentGroupObject as HL7Segment;
                        segment.Encode(seps, sb);
                        sb.Append(seps.SegmentSeparator);
                    }
                }
            }
        }
        public static object Parse(Type type, string componentForm, HL7Separators sep)
        {
            object component;

            // A component can either be a string, or it will consist of sub-components.
            if (type.Equals(typeof(string)))
            {
                component = sep.Decode(componentForm);
            }
            else
            {
                FieldInfo[] subcomponents    = type.GetFields();
                string[]    subcomponentForm = componentForm.Split(sep.SubcomponentSeparator);
                int         n = Math.Min(subcomponents.Length, subcomponentForm.Length);

                // Invoke the constructor that takes no parameters
                component = type.GetConstructor(System.Type.EmptyTypes).Invoke(null);
                for (int i = 0; i < n; i++)
                {
                    // Each subcomponent must be a string
                    if (subcomponents[i].FieldType.Equals(typeof(string)))
                    {
                        subcomponents[i].SetValue(component, sep.Decode(subcomponentForm[i]));
                    }
                    else if (subcomponents[i].FieldType.Equals(typeof(HL7.Common.DataStructure.HD))) // For OBR segment PrincipalResultsInterpreter field we have assigningAuthority that needs to be set
                    {
                        object      objHD           = new HL7.Common.DataStructure.HD();
                        FieldInfo[] subcomponentsHD = objHD.GetType().GetFields();
                        for (int j = 0; j < subcomponentsHD.Length; j++)
                        {
                            if (subcomponentsHD[j].Name == "universalID")                            //  Set the UniversalID
                            {
                                subcomponentsHD[j].SetValue(objHD, sep.Decode(subcomponentForm[i])); //
                                subcomponents[i].SetValue(component, objHD);
                            }
                        }
                    }
                    else
                    {
                        throw new HL7ParseException(string.Format(ConstantsResource.SubcomponentNotString, subcomponents[i].GetType()));
                    }
                }
            }
            return(component);
        }
Beispiel #7
0
        public static object Parse(Type type, string fieldForm, HL7Separators sep)
        {
            object field;

            // A field can be an array of repeats, or a string identifier, or a data structure with components
            if (type.IsArray)
            {
                Type     elementType = type.GetElementType();
                string[] elementForm;
                if (fieldForm.IndexOf(sep.FieldRepeatSeparator) == -1 && fieldForm.IndexOf(sep.ComponentSeparator) > -1 && elementType.Equals(typeof(string)))
                {
                    elementForm = fieldForm.Split(sep.ComponentSeparator);
                }
                else
                {
                    elementForm = fieldForm.Split(sep.FieldRepeatSeparator);
                }
                Array array = Array.CreateInstance(elementType, elementForm.Length);
                for (int i = 0; i < elementForm.Length; i++)
                {
                    array.SetValue(HL7Field.Parse(elementType, elementForm[i], sep), i);
                }
                field = array;
            }
            else if (type.Equals(typeof(string)))
            {
                field = sep.Decode(fieldForm);
            }
            else
            {
                FieldInfo[] components    = type.GetFields();
                string[]    componentForm = fieldForm.Split(sep.ComponentSeparator);
                int         n             = Math.Min(components.Length, componentForm.Length);

                // Invoke the constructor that takes no parameters
                field = type.GetConstructor(System.Type.EmptyTypes).Invoke(null);
                for (int i = 0; i < n; i++)
                {
                    object value = HL7Component.Parse(components[i].FieldType, componentForm[i], sep);
                    components[i].SetValue(field, value);
                }
            }
            return(field);
        }
Beispiel #8
0
        public static HL7Segment Parse(string segmentForm, HL7Separators sep)
        {
            // Split the segment into fields and create the object for the indicated segment identifier
            string[]   fieldForm = segmentForm.Split(sep.FieldSeparator);
            HL7Segment segment   = CreateBlankSegment(fieldForm[0]);

            if (segment == null)
            {
                return(new UnknownSegment()
                {
                    FieldForm = fieldForm
                });
            }

            // Parse each of the fields according to its declared identifier in the segment structure.
            // Some fields will be repeating, some will be strings and some will have components.
            PopulateSegment(sep, fieldForm, segment);
            return(segment);
        }
Beispiel #9
0
        /// <summary>
        /// Cleans up an HL7 message by removing redundant separators.
        /// </summary>
        /// <param name="seps">The defined separators for the message</param>
        /// <param name="messageForm">The message to be cleaned up</param>
        /// <returns>The cleaned message</returns>
        private static string Cleanup(HL7Separators seps, string messageForm)
        {
            // Save the first 8 characters which contain the HL7 encoding characters that should not be normalised.
            const int PREAMBLE_LENGTH = 8;

            string preamble = messageForm.Substring(0, PREAMBLE_LENGTH);

            messageForm = messageForm.Substring(PREAMBLE_LENGTH);

            // e.g. input:    a&^&~&^&|&^&~&^&\r

            //     step 1:    a^&~^&|^&~^&\r      (removed & before ^)
            //     step 2:    a^~^&|^~^&\r        (removed & before ~)
            //     step 3:    a^~^|^~^&\r         (removed & before |)
            //     step 4:    a^~^|^~^\r          (removed & before \r)

            //     step 5:    a~^|~^\r            (removed ^ before ~)
            //     step 6:    a~|~^\r             (removed ^ before |)
            //     step 7:    a~|~\r              (removed ^ before \r)

            //     step 8:    a|~\r               (removed ~ before |)
            //     step 9:    a|\r                (removed ~ before \r)

            //     step 10:   a\r                 (removed | before \r)

            RemoveRedundantSeparator(ref messageForm, seps.SubcomponentSeparator, seps.ComponentSeparator);
            RemoveRedundantSeparator(ref messageForm, seps.SubcomponentSeparator, seps.FieldRepeatSeparator);
            RemoveRedundantSeparator(ref messageForm, seps.SubcomponentSeparator, seps.FieldSeparator);
            RemoveRedundantSeparator(ref messageForm, seps.SubcomponentSeparator, seps.SegmentSeparator);

            RemoveRedundantSeparator(ref messageForm, seps.ComponentSeparator, seps.FieldRepeatSeparator);
            RemoveRedundantSeparator(ref messageForm, seps.ComponentSeparator, seps.FieldSeparator);
            RemoveRedundantSeparator(ref messageForm, seps.ComponentSeparator, seps.SegmentSeparator);

            RemoveRedundantSeparator(ref messageForm, seps.FieldRepeatSeparator, seps.FieldSeparator);
            RemoveRedundantSeparator(ref messageForm, seps.FieldRepeatSeparator, seps.SegmentSeparator);

            RemoveRedundantSeparator(ref messageForm, seps.FieldSeparator, seps.SegmentSeparator);

            return(preamble + messageForm);
        }
Beispiel #10
0
        /// <summary>
        /// Parses each of the fields according to its declared identifier in the segment structure.
        /// Ignores any extra fields either in the received segment or in the structure.
        /// </summary>
        /// <param HL7Name="sep">Separators to use for repeating fields, components and subcomponents</param>
        /// <param HL7Name="fieldForm">Encoded segment split into fields, where fieldForm[0] is the segment name</param>
        /// <param HL7Name="segment">Empty object of desired segment structure</param>
        private static void PopulateSegment(HL7Separators sep, string[] fieldForm, HL7Segment segment)
        {
            FieldInfo[] fields = segment.GetType().GetFields();

            // Subtract one from the number of fields in the received segment to avoid counting the segment name.
            int offset = 1;

            // Except when segment is MSH, then have no offset but the first field is the field separator.
            if (fieldForm[0].Equals("MSH"))
            {
                fields[0].SetValue(segment, "" + sep.FieldSeparator);
                offset = 0;
            }

            int n = Math.Min(fields.Length, fieldForm.Length - 1);

            for (int i = 1 - offset; i < n; i++)
            {
                object value = HL7Field.Parse(fields[i].FieldType, fieldForm[i + offset], sep);
                fields[i].SetValue(segment, value);
            }
        }
        /// <summary>
        /// Creates a negative HL7 acknowledgement for an unparseable message.
        /// </summary>
        /// <param HL7Name="errorMessage">A description of the error</param>
        /// <returns>The HL7 acknowledgement</returns>
        public static HL7Acknowledgement AcknowledgeUnparseableMessage(string errorMessage)
        {
            HL7Separators      typical = new HL7Separators();
            HL7Acknowledgement ack     = new HL7Acknowledgement();

            ack.MessageHeader = new MSH();
            ack.MessageHeader.FieldSeparator     = typical.FieldSeparator.ToString();
            ack.MessageHeader.EncodingCharacters = typical.EncodingCharacters;
            ack.MessageHeader.SendingApplication = new HD()
            {
                namespaceID = "HIPS"
            };
            ack.MessageHeader.SendingFacility = new HD()
            {
                namespaceID = "HIPS"
            };
            ack.MessageHeader.ReceivingApplication = new HD()
            {
                namespaceID = "HIPS"
            };
            ack.MessageHeader.ReceivingFacility = new HD()
            {
                namespaceID = "HIPS"
            };
            ack.MessageHeader.DateTimeOfMessage = new TS()
            {
                TimestampValue = DateTime.Now
            };
            ack.MessageHeader.MessageControlID            = NewMessageControlID();
            ack.MessageAcknowledgement                    = new MSA();
            ack.MessageAcknowledgement.AcknowledgmentCode = "AE";
            ack.MessageAcknowledgement.ErrorCondition     = new CE()
            {
                text = errorMessage
            };
            return(ack);
        }
        internal static void Encode(HL7Separators seps, System.Text.StringBuilder sb, Type type, object value)
        {
            // A component is either empty, a string or an HL7 data structure containing subcomponents.
            if (value == null)
            {
                // Do nothing
            }
            else if (value is string)
            {
                sb.Append(seps.Encode(value as string));
            }
            else
            {
                foreach (FieldInfo subcomponent in type.GetFields())
                {
                    // A subcomponent is always a string
                    sb.Append(seps.Encode(subcomponent.GetValue(value) as string));
                    sb.Append(seps.SubcomponentSeparator);
                }

                // Remove the extraneous subcomponent separator
                sb.Remove(sb.Length - 1, 1);
            }
        }