Пример #1
0
        /// <summary> Populates the given Element with data from the given Segment, by inserting
        /// Elements corresponding to the Segment's fields, their components, etc.  Returns
        /// true if there is at least one data value in the segment.
        /// </summary>
        public virtual bool Encode(ISegment segmentObject, XmlElement segmentElement)
        {
            var hasValue = false;
            var n        = segmentObject.NumFields();

            for (var i = 1; i <= n; i++)
            {
                var name = MakeElementName(segmentObject, i);
                var reps = segmentObject.GetField(i);
                for (var j = 0; j < reps.Length; j++)
                {
                    var newNode           = segmentElement.OwnerDocument.CreateElement(name);
                    var componentHasValue = Encode(reps[j], newNode);
                    if (componentHasValue)
                    {
                        try
                        {
                            segmentElement.AppendChild(newNode);
                        }
                        catch (Exception e)
                        {
                            throw new HL7Exception("DOMException encoding Segment: ", ErrorCode.APPLICATION_INTERNAL_ERROR, e);
                        }

                        hasValue = true;
                    }
                }
            }

            return(hasValue);
        }
Пример #2
0
        /// <summary>
        /// Populates the given Element with data from the given Segment, by inserting Elements
        /// corresponding to the Segment's fields, their components, etc.  Returns true if there is at
        /// least one data value in the segment.
        /// </summary>
        ///
        /// <exception cref="HL7Exception"> Thrown when a HL 7 error condition occurs. </exception>
        ///
        /// <param name="segmentObject">    The segment object. </param>
        /// <param name="segmentElement">   Element describing the segment. </param>
        ///
        /// <returns>   true if it succeeds, false if it fails. </returns>

        public virtual bool Encode(ISegment segmentObject, System.Xml.XmlElement segmentElement)
        {
            bool hasValue = false;
            int  n        = segmentObject.NumFields();

            for (int i = 1; i <= n; i++)
            {
                System.String name = MakeElementName(segmentObject, i);
                IType[]       reps = segmentObject.GetField(i);
                for (int j = 0; j < reps.Length; j++)
                {
                    System.Xml.XmlElement newNode = segmentElement.OwnerDocument.CreateElement(name);
                    bool componentHasValue        = Encode(reps[j], newNode);
                    if (componentHasValue)
                    {
                        try
                        {
                            segmentElement.AppendChild(newNode);
                        }
                        catch (System.Exception e)
                        {
                            throw new HL7Exception(
                                      "DOMException encoding Segment: ",
                                      HL7Exception.APPLICATION_INTERNAL_ERROR,
                                      e);
                        }
                        hasValue = true;
                    }
                }
            }
            return(hasValue);
        }
Пример #3
0
        /// <summary> Populates the given error segment with information from this Exception.</summary>
        // TODO: this is out of sync with hapi see
        // https://github.com/hapifhir/hapi-hl7v2/blob/809516e3f4851d7cd97573efb6dedf24959a1063/hapi-base/src/main/java/ca/uhn/hl7v2/AbstractHL7Exception.java#L134
        public virtual void populate(ISegment errorSegment)
        {
            //make sure it's an ERR
            if (!errorSegment.GetStructureName().Equals("ERR"))
            {
                throw new HL7Exception("Can only populate an ERR segment with an exception -- got: " +
                                       errorSegment.GetType().FullName);
            }

            var rep = errorSegment.GetField(1).Length;             //append after existing reps

            if (SegmentName != null)
            {
                Terser.Set(errorSegment, 1, rep, 1, 1, SegmentName);
            }


            if (SegmentRepetition >= 0)
            {
                Terser.Set(errorSegment, 1, rep, 2, 1, Convert.ToString(SegmentRepetition));
            }


            if (FieldPosition >= 0)
            {
                Terser.Set(errorSegment, 1, rep, 3, 1, Convert.ToString(FieldPosition));
            }

            Terser.Set(errorSegment, 1, rep, 4, 1, Convert.ToString(ErrorCode));
            // this replaces the need to connect to the database
            Terser.Set(errorSegment, 1, rep, 4, 2, ErrorCode.GetName());
            Terser.Set(errorSegment, 1, rep, 4, 3, "hl70357");
            Terser.Set(errorSegment, 1, rep, 4, 5, Message);
        }
Пример #4
0
 private void ParseReps(ISegment segmentObject, System.Xml.XmlElement segmentElement, System.String fieldName, int fieldNum)
 {
     System.Xml.XmlNodeList reps = segmentElement.GetElementsByTagName(fieldName);
     for (int i = 0; i < reps.Count; i++)
     {
         Parse(segmentObject.GetField(fieldNum, i), (System.Xml.XmlElement)reps.Item(i));
     }
 }
Пример #5
0
        private void ParseReps(ISegment segmentObject, XmlElement segmentElement, string fieldName, int fieldNum)
        {
            var reps = segmentElement.GetElementsByTagName(fieldName);

            for (var i = 0; i < reps.Count; i++)
            {
                Parse(segmentObject.GetField(fieldNum, i), (XmlElement)reps.Item(i));
            }
        }
Пример #6
0
        /// <summary>
        /// Sets the data type of field 5 in the given OBX segment to the value of OBX-2.  The argument
        /// is a Segment as opposed to a particular OBX because it is meant to work with any version.
        /// </summary>
        ///
        /// <exception cref="HL7Exception"> Thrown when a HL 7 error condition occurs. </exception>
        ///
        /// <param name="segment">  The segment. </param>
        /// <param name="factory">  The factory. </param>

        public static void fixOBX5(ISegment segment, IModelClassFactory factory)
        {
            try
            {
                //get unqualified class name
                IPrimitive obx2 = (IPrimitive)segment.GetField(2, 0);
                Varies     v    = (Varies)segment.GetField(5, 0);

                if (obx2.Value == null)
                {
                    if (v.Data != null)
                    {
                        if (!(v.Data is IPrimitive) || ((IPrimitive)v.Data).Value != null)
                        {
                            throw new HL7Exception(
                                      "OBX-5 is valued, but OBX-2 is not.  A datatype for OBX-5 must be specified using OBX-2.",
                                      HL7Exception.REQUIRED_FIELD_MISSING);
                        }
                    }
                }
                else
                {
                    //set class
                    System.Type c = factory.GetTypeClass(obx2.Value, segment.Message.Version);
                    //                Class c = NHapi.Base.Parser.ParserBase.findClass(obx2.getValue(),
                    //                                                segment.getMessage().getVersion(),
                    //                                                "datatype");
                    v.Data =
                        (IType)c.GetConstructor(new[] { typeof(IMessage) }).Invoke(new System.Object[] { v.Message });
                }
            }
            catch (HL7Exception e)
            {
                throw e;
            }
            catch (System.Exception e)
            {
                throw new HL7Exception(
                          e.GetType().FullName + " trying to set data type of OBX-5",
                          HL7Exception.APPLICATION_INTERNAL_ERROR,
                          e);
            }
        }
Пример #7
0
        /// <summary> Sets the data type of field 5 in the given OBX segment to the value of OBX-2.  The argument
        /// is a Segment as opposed to a particular OBX because it is meant to work with any version.
        /// </summary>
        public static void fixOBX5(ISegment segment, IModelClassFactory factory)
        {
            try
            {
                //get unqualified class name
                IPrimitive obx2 = (IPrimitive)segment.GetField(2, 0);

                foreach (IType repetition in segment.GetField(5))
                {
                    Varies v = (Varies)repetition;

                    if (obx2.Value == null)
                    {
                        if (v.Data != null)
                        {
                            if (!(v.Data is IPrimitive) || ((IPrimitive)v.Data).Value != null)
                            {
                                throw new HL7Exception(
                                          "OBX-5 is valued, but OBX-2 is not.  A datatype for OBX-5 must be specified using OBX-2.",
                                          ErrorCode.REQUIRED_FIELD_MISSING);
                            }
                        }
                    }
                    else
                    {
                        UseDTInsteadOfDTMForEarlierVersionsOfHL7(segment, obx2);

                        Type c = factory.GetTypeClass(obx2.Value, segment.Message.Version);
                        v.Data = (IType)c.GetConstructor(new [] { typeof(IMessage), typeof(String) }).Invoke(new Object[] { v.Message, v.Description });
                    }
                }
            }
            catch (HL7Exception e)
            {
                throw e;
            }
            catch (Exception e)
            {
                throw new HL7Exception(e.GetType().FullName + " trying to set data type of OBX-5",
                                       ErrorCode.APPLICATION_INTERNAL_ERROR, e);
            }
        }
Пример #8
0
		/// <summary> Copies contents from the source segment to the destination segment.  This 
		/// method calls copy(Type, Type) on each repetition of each field (see additional 
		/// behavioural description there).  An attempt is made to copy each repetition of 
		/// each field in the source segment, regardless of whether the corresponding 
		/// destination field is repeating or even exists.  
		/// </summary>
		/// <param name="from">the segment from which data are copied 
		/// </param>
		/// <param name="to">the segment into which data are copied
		/// </param>
		public static void copy(ISegment from, ISegment to)
		{
			int n = from.NumFields();
			for (int i = 1; i <= n; i++)
			{
				IType[] reps = from.GetField(i);
				for (int j = 0; j < reps.Length; j++)
				{
					copy(reps[j], to.GetField(i, j));
				}
			}
		}
Пример #9
0
        /// <summary> Copies contents from the source segment to the destination segment.  This
        /// method calls copy(Type, Type) on each repetition of each field (see additional
        /// behavioural description there).  An attempt is made to copy each repetition of
        /// each field in the source segment, regardless of whether the corresponding
        /// destination field is repeating or even exists.
        /// </summary>
        /// <param name="from">the segment from which data are copied.
        /// </param>
        /// <param name="to">the segment into which data are copied.
        /// </param>
        public static void Copy(ISegment from, ISegment to)
        {
            var n = from.NumFields();

            for (var i = 1; i <= n; i++)
            {
                var reps = from.GetField(i);
                for (var j = 0; j < reps.Length; j++)
                {
                    Copy(reps[j], to.GetField(i, j));
                }
            }
        }
Пример #10
0
        /// <summary> Copies contents from the source segment to the destination segment.  This
        /// method calls copy(Type, Type) on each repetition of each field (see additional
        /// behavioural description there).  An attempt is made to copy each repetition of
        /// each field in the source segment, regardless of whether the corresponding
        /// destination field is repeating or even exists.
        /// </summary>
        /// <param name="from">the segment from which data are copied
        /// </param>
        /// <param name="to">the segment into which data are copied
        /// </param>
        public static void copy(ISegment from, ISegment to)
        {
            int n = from.NumFields();

            for (int i = 1; i <= n; i++)
            {
                IType[] reps = from.GetField(i);
                for (int j = 0; j < reps.Length; j++)
                {
                    copy(reps[j], to.GetField(i, j));
                }
            }
        }
Пример #11
0
        /// <summary>
        /// Formats a <see cref="IMessage"/> object into an HL7 message string using the given encoding.
        /// </summary>
        /// <param name="source">An <see cref="IMessage"/> object from which to construct an encoded message string.</param>
        /// <param name="encodingChars">Encoding characters to be used.</param>
        /// <returns>The encoded message.</returns>
        /// <exception cref="HL7Exception">Thrown if the data fields in the message do not permit encoding (e.g. required fields are null).</exception>
        /// <exception cref="EncodingNotSupportedException">Thrown if the requested encoding is not supported by this parser.</exception>
        public static string Encode(ISegment source, EncodingCharacters encodingChars)
        {
            var result = new StringBuilder();

            result.Append(source.GetStructureName());
            result.Append(encodingChars.FieldSeparator);

            // start at field 2 for MSH segment because field 1 is the field delimiter
            var startAt = 1;

            if (IsDelimDefSegment(source.GetStructureName()))
            {
                startAt = 2;
            }

            // loop through fields; for every field delimit any repetitions and add field delimiter after ...
            var numFields = source.NumFields();

            for (var i = startAt; i <= numFields; i++)
            {
                try
                {
                    var reps = source.GetField(i);
                    for (var j = 0; j < reps.Length; j++)
                    {
                        var fieldText = Encode(reps[j], encodingChars);

                        // if this is MSH-2, then it shouldn't be escaped, so un-escape it again
                        if (IsDelimDefSegment(source.GetStructureName()) && i == 2)
                        {
                            fieldText = Escape.UnescapeText(fieldText, encodingChars);
                        }

                        result.Append(fieldText);
                        if (j < reps.Length - 1)
                        {
                            result.Append(encodingChars.RepetitionSeparator);
                        }
                    }
                }
                catch (HL7Exception e)
                {
                    Log.Error("Error while encoding segment: ", e);
                }

                result.Append(encodingChars.FieldSeparator);
            }

            // strip trailing delimiters ...
            return(StripExtraDelimiters(result.ToString(), encodingChars.FieldSeparator));
        }
Пример #12
0
        /// <summary>
        /// Encode un segment.
        /// </summary>
        /// <param name="segment">Segment à encoder.</param>
        /// <param name="encChars">Caractères d'encodage utilisés.</param>
        /// <returns></returns>
        public static string Encode(ISegment segment, EncodingCharacters encChars)
        {
            StringBuilder retSegment = new StringBuilder();

            // Code du segment et premier séparateur de champ
            retSegment.Append(segment.SegmentName);
            retSegment.Append(encChars.FieldSeparator);

            // Si segment MSH : position de départ sur MSH-2 car MSH-1 correspond au séparateur de champ
            int startPos = InteropUtil.IsSegmentDefDelimiters(segment.SegmentName) ? 2 : 1;

            // Parcours des champs
            for (int i = startPos; i <= segment.Fields.Count; i++)
            {
                try
                {
                    // Parcours des répétitions
                    IType[] repetitions = segment.GetField(i);

                    for (int j = 0; j < repetitions.Length; j++)
                    {
                        string repValue = PipeParser.Encode(repetitions[j], encChars);

                        // Si MSH-2 : il faut annuler l'échappement des caractères réservés
                        if (InteropUtil.IsSegmentDefDelimiters(segment.SegmentName) && i == 2)
                        {
                            repValue = EscapeCharacterUtil.Unescape(repValue, encChars);
                        }

                        retSegment.Append(repValue);

                        if (j < repetitions.Length - 1)
                        {
                            retSegment.Append(encChars.RepetitionSeparator);
                        }
                    }
                }
                catch
                {
                    throw;
                }

                retSegment.Append(encChars.FieldSeparator);
            }

            return(InteropUtil.RemoveExtraDelimiters(retSegment.ToString(), encChars.FieldSeparator));
        }
Пример #13
0
        /// <summary> Populates the given error segment with information from this Exception.</summary>
        public virtual void populate(ISegment errorSegment)
        {
            //make sure it's an ERR
            if (!errorSegment.GetStructureName().Equals("ERR"))
            {
                throw new HL7Exception("Can only populate an ERR segment with an exception -- got: " +
                                       errorSegment.GetType().FullName);
            }

            int rep = errorSegment.GetField(1).Length;             //append after existing reps

            if (SegmentName != null)
            {
                Terser.Set(errorSegment, 1, rep, 1, 1, SegmentName);
            }

            if (SegmentRepetition >= 0)
            {
                Terser.Set(errorSegment, 1, rep, 2, 1, Convert.ToString(SegmentRepetition));
            }

            if (FieldPosition >= 0)
            {
                Terser.Set(errorSegment, 1, rep, 3, 1, Convert.ToString(FieldPosition));
            }

            Terser.Set(errorSegment, 1, rep, 4, 1, Convert.ToString(errCode));
            Terser.Set(errorSegment, 1, rep, 4, 3, "hl70357");
            Terser.Set(errorSegment, 1, rep, 4, 5, Message);

            //try to get error condition text
            try
            {
                String desc = TableRepository.Instance.getDescription(357, Convert.ToString(errCode));
                Terser.Set(errorSegment, 1, rep, 4, 2, desc);
            }
            catch (LookupException e)
            {
                ourLog.Debug("Warning: LookupException getting error condition text (are we connected to a TableRepository?)", e);
            }
            catch (InvalidOperationException e)
            {
                ourLog.Debug("Warning: InvalidOperationException getting error condition text (are we connected to a TableRepository? Is a valid ConnectionString configured?)", e);
            }
        }
Пример #14
0
        /// <summary> Sets the data type of field 5 in the given OBX segment to the value of OBX-2.  The argument 
        /// is a Segment as opposed to a particular OBX because it is meant to work with any version.  
        /// </summary>
        public static void fixOBX5(ISegment segment, IModelClassFactory factory)
        {
            try
            {
                //get unqualified class name
                IPrimitive obx2 = (IPrimitive)segment.GetField(2, 0);
                Varies v = (Varies)segment.GetField(5, 0);

                if (obx2.Value == null)
                {
                    if (v.Data != null)
                    {
                        if (!(v.Data is IPrimitive) || ((IPrimitive)v.Data).Value != null)
                        {
                            throw new HL7Exception("OBX-5 is valued, but OBX-2 is not.  A datatype for OBX-5 must be specified using OBX-2.", HL7Exception.REQUIRED_FIELD_MISSING);
                        }
                    }
                }
                else
                {
                    //set class
                    System.Type c = factory.GetTypeClass(obx2.Value, segment.Message.Version);
                    //                Class c = NHapi.Base.Parser.ParserBase.findClass(obx2.getValue(),
                    //                                                segment.getMessage().getVersion(),
                    //                                                "datatype");
                    v.Data = (IType)c.GetConstructor(new System.Type[] { typeof(IMessage) }).Invoke(new System.Object[] { v.Message });
                }
            }
            catch (HL7Exception e)
            {
                throw e;
            }
            catch (System.Exception e)
            {
                throw new HL7Exception(e.GetType().FullName + " trying to set data type of OBX-5", HL7Exception.APPLICATION_INTERNAL_ERROR, e);
            }
        }
Пример #15
0
		private void ParseReps(ISegment segmentObject, XmlElement segmentElement, String fieldName, int fieldNum)
		{
			XmlNodeList reps = segmentElement.GetElementsByTagName(fieldName);
			for (int i = 0; i < reps.Count; i++)
			{
				Parse(segmentObject.GetField(fieldNum, i), (XmlElement) reps.Item(i));
			}
		}
Пример #16
0
		/// <summary> Populates the given Element with data from the given Segment, by inserting
		/// Elements corresponding to the Segment's fields, their components, etc.  Returns 
		/// true if there is at least one data value in the segment.   
		/// </summary>
		public virtual bool Encode(ISegment segmentObject, XmlElement segmentElement)
		{
			bool hasValue = false;
			int n = segmentObject.NumFields();
			for (int i = 1; i <= n; i++)
			{
				String name = MakeElementName(segmentObject, i);
				IType[] reps = segmentObject.GetField(i);
				for (int j = 0; j < reps.Length; j++)
				{
					XmlElement newNode = segmentElement.OwnerDocument.CreateElement(name);
					bool componentHasValue = Encode(reps[j], newNode);
					if (componentHasValue)
					{
						try
						{
							segmentElement.AppendChild(newNode);
						}
						catch (Exception e)
						{
							throw new HL7Exception("DOMException encoding Segment: ", HL7Exception.APPLICATION_INTERNAL_ERROR, e);
						}
						hasValue = true;
					}
				}
			}
			return hasValue;
		}
Пример #17
0
        /// <summary> Parses a segment string and populates the given Segment object.  Unexpected fields are
        /// added as Varies' at the end of the segment.
        ///
        /// </summary>
        /// <throws>  HL7Exception if the given string does not contain the </throws>
        /// <summary>      given segment or if the string is not encoded properly
        /// </summary>
        public virtual void Parse(ISegment destination, System.String segment, EncodingCharacters encodingChars)
        {
            int fieldOffset = 0;

            if (IsDelimDefSegment(destination.GetStructureName()))
            {
                fieldOffset = 1;
                //set field 1 to fourth character of string
                Terser.Set(destination, 1, 0, 1, 1, System.Convert.ToString(encodingChars.FieldSeparator));
            }

            System.String[] fields = Split(segment, System.Convert.ToString(encodingChars.FieldSeparator));
            //destination.setName(fields[0]);
            for (int i = 1; i < fields.Length; i++)
            {
                System.String[] reps = Split(fields[i], System.Convert.ToString(encodingChars.RepetitionSeparator));
                if (log.DebugEnabled)
                {
                    log.Debug(reps.Length + "reps delimited by: " + encodingChars.RepetitionSeparator);
                }

                //MSH-2 will get split incorrectly so we have to fudge it ...
                bool isMSH2 = IsDelimDefSegment(destination.GetStructureName()) && i + fieldOffset == 2;
                if (isMSH2)
                {
                    reps    = new System.String[1];
                    reps[0] = fields[i];
                }

                for (int j = 0; j < reps.Length; j++)
                {
                    try
                    {
                        System.Text.StringBuilder statusMessage = new System.Text.StringBuilder("Parsing field ");
                        statusMessage.Append(i + fieldOffset);
                        statusMessage.Append(" repetition ");
                        statusMessage.Append(j);
                        log.Debug(statusMessage.ToString());
                        //parse(destination.GetField(i + fieldOffset, j), reps[j], encodingChars, false);

                        IType field = destination.GetField(i + fieldOffset, j);
                        if (isMSH2)
                        {
                            Terser.getPrimitive(field, 1, 1).Value = reps[j];
                        }
                        else
                        {
                            Parse(field, reps[j], encodingChars);
                        }
                    }
                    catch (HL7Exception e)
                    {
                        //set the field location and throw again ...
                        e.FieldPosition     = i;
                        e.SegmentRepetition = MessageIterator.getIndex(destination.ParentStructure, destination).rep;
                        e.SegmentName       = destination.GetStructureName();
                        throw e;
                    }
                }
            }

            //set data type of OBX-5
            if (destination.GetType().FullName.IndexOf("OBX") >= 0)
            {
                Varies.fixOBX5(destination, Factory);
            }
        }
Пример #18
0
        /// <summary>
        /// Parses a segment string and populates the given Segment object.
        /// <para>
        /// Unexpected fields are added as Varies' at the end of the segment.
        /// </para>
        /// </summary>
        /// <param name="destination">Segment to parse the segment string into.</param>
        /// <param name="segment">Encoded segment.</param>
        /// <param name="encodingChars">Encoding characters to be used.</param>
        /// <param name="repetition">The repetition number of this segment within its group.</param>
        /// <param name="parserOptions">Contains configuration that will be applied when parsing.</param>
        /// <exception cref="HL7Exception">
        /// If the given string does not contain the given segment or if the string is not encoded properly.
        /// </exception>
        public virtual void Parse(ISegment destination, string segment, EncodingCharacters encodingChars, int repetition, ParserOptions parserOptions)
        {
            parserOptions = parserOptions ?? DefaultParserOptions;

            var fieldOffset = 0;

            if (IsDelimDefSegment(destination.GetStructureName()))
            {
                fieldOffset = 1;

                // set field 1 to fourth character of string
                Terser.Set(destination, 1, 0, 1, 1, Convert.ToString(encodingChars.FieldSeparator));
            }

            var fields = Split(segment, Convert.ToString(encodingChars.FieldSeparator));

            for (var i = 1; i < fields.Length; i++)
            {
                var reps = Split(fields[i], Convert.ToString(encodingChars.RepetitionSeparator));
                if (Log.DebugEnabled)
                {
                    Log.Debug(reps.Length + "reps delimited by: " + encodingChars.RepetitionSeparator);
                }

                // MSH-2 will get split incorrectly so we have to fudge it ...
                var isMSH2 = IsDelimDefSegment(destination.GetStructureName()) && i + fieldOffset == 2;
                if (isMSH2)
                {
                    reps    = new string[1];
                    reps[0] = fields[i];
                }

                for (var j = 0; j < reps.Length; j++)
                {
                    try
                    {
                        var statusMessage = $"Parsing field {i + fieldOffset} repetition {j}";
                        Log.Debug(statusMessage);

                        var field = destination.GetField(i + fieldOffset, j);
                        if (isMSH2)
                        {
                            Terser.GetPrimitive(field, 1, 1).Value = reps[j];
                        }
                        else
                        {
                            Parse(field, reps[j], encodingChars);
                        }
                    }
                    catch (HL7Exception e)
                    {
                        // set the field location and throw again ...
                        e.FieldPosition = i;
                        if (repetition > 1)
                        {
                            e.SegmentRepetition = repetition;
                        }

                        e.SegmentName = destination.GetStructureName();
                        throw;
                    }
                }
            }

            // set data type of OBX-5
            if (destination.GetType().FullName.IndexOf("OBX") >= 0)
            {
                Varies.FixOBX5(destination, Factory, parserOptions);
            }
        }
Пример #19
0
        /// <summary> Returns the Primitive object at the given location.</summary>
        private static IPrimitive getPrimitive(ISegment segment, int field, int rep, int component, int subcomponent)
        {
            IType type = segment.GetField(field, rep);

            return(getPrimitive(type, component, subcomponent));
        }
Пример #20
0
		/// <summary> Sets the data type of field 5 in the given OBX segment to the value of OBX-2.  The argument 
		/// is a Segment as opposed to a particular OBX because it is meant to work with any version.  
		/// </summary>
		public static void fixOBX5(ISegment segment, IModelClassFactory factory)
		{
			try
			{
				//get unqualified class name
				IPrimitive obx2 = (IPrimitive) segment.GetField(2, 0);

				foreach (IType repetition in segment.GetField(5))
				{
					Varies v = (Varies) repetition;

					if (obx2.Value == null)
					{
						if (v.Data != null)
						{
							if (!(v.Data is IPrimitive) || ((IPrimitive) v.Data).Value != null)
							{
								throw new HL7Exception(
									"OBX-5 is valued, but OBX-2 is not.  A datatype for OBX-5 must be specified using OBX-2.",
									HL7Exception.REQUIRED_FIELD_MISSING);
							}
						}
					}
					else
					{
						Type c = factory.GetTypeClass(obx2.Value, segment.Message.Version);
						v.Data = (IType) c.GetConstructor(new [] {typeof (IMessage), typeof(String)}).Invoke(new Object[] {v.Message, v.Description});
					}
				}
			}
			catch (HL7Exception e)
			{
				throw e;
			}
			catch (Exception e)
			{
				throw new HL7Exception(e.GetType().FullName + " trying to set data type of OBX-5",
					HL7Exception.APPLICATION_INTERNAL_ERROR, e);
			}
		}
Пример #21
0
		public static String Encode(ISegment source, EncodingCharacters encodingChars)
		{
			StringBuilder result = new StringBuilder();
			result.Append(source.GetStructureName());
			result.Append(encodingChars.FieldSeparator);

			//start at field 2 for MSH segment because field 1 is the field delimiter
			int startAt = 1;
			if (IsDelimDefSegment(source.GetStructureName()))
				startAt = 2;

			//loop through fields; for every field delimit any repetitions and add field delimiter after ...
			int numFields = source.NumFields();
			for (int i = startAt; i <= numFields; i++)
			{
				try
				{
					IType[] reps = source.GetField(i);
					for (int j = 0; j < reps.Length; j++)
					{
						String fieldText = Encode(reps[j], encodingChars);
						//if this is MSH-2, then it shouldn't be escaped, so unescape it again
						if (IsDelimDefSegment(source.GetStructureName()) && i == 2)
							fieldText = Escape.unescape(fieldText, encodingChars);
						result.Append(fieldText);
						if (j < reps.Length - 1)
							result.Append(encodingChars.RepetitionSeparator);
					}
				}
				catch (HL7Exception e)
				{
					log.Error("Error while encoding segment: ", e);
				}
				result.Append(encodingChars.FieldSeparator);
			}

			//strip trailing delimiters ...
			return StripExtraDelimiters(result.ToString(), encodingChars.FieldSeparator);
		}
Пример #22
0
		/// <summary> Parses a segment string and populates the given Segment object.  Unexpected fields are
		/// added as Varies' at the end of the segment.  
		/// 
		/// </summary>
		/// <throws>  HL7Exception if the given string does not contain the </throws>
		/// <summary>      given segment or if the string is not encoded properly
		/// </summary>
		public virtual void Parse(ISegment destination, String segment, EncodingCharacters encodingChars)
		{
			int fieldOffset = 0;
			if (IsDelimDefSegment(destination.GetStructureName()))
			{
				fieldOffset = 1;
				//set field 1 to fourth character of string
				Terser.Set(destination, 1, 0, 1, 1, Convert.ToString(encodingChars.FieldSeparator));
			}

			String[] fields = Split(segment, Convert.ToString(encodingChars.FieldSeparator));

			for (int i = 1; i < fields.Length; i++)
			{
				String[] reps = Split(fields[i], Convert.ToString(encodingChars.RepetitionSeparator));
				if (log.DebugEnabled)
				{
					log.Debug(reps.Length + "reps delimited by: " + encodingChars.RepetitionSeparator);
				}

				//MSH-2 will get split incorrectly so we have to fudge it ...
				bool isMSH2 = IsDelimDefSegment(destination.GetStructureName()) && i + fieldOffset == 2;
				if (isMSH2)
				{
					reps = new String[1];
					reps[0] = fields[i];
				}

				for (int j = 0; j < reps.Length; j++)
				{
					try
					{
						StringBuilder statusMessage = new StringBuilder("Parsing field ");
						statusMessage.Append(i + fieldOffset);
						statusMessage.Append(" repetition ");
						statusMessage.Append(j);
						log.Debug(statusMessage.ToString());

						IType field = destination.GetField(i + fieldOffset, j);
						if (isMSH2)
						{
							Terser.getPrimitive(field, 1, 1).Value = reps[j];
						}
						else
						{
							Parse(field, reps[j], encodingChars);
						}
					}
					catch (HL7Exception e)
					{
						//set the field location and throw again ...
						e.FieldPosition = i + fieldOffset;
						e.SegmentRepetition = MessageIterator.getIndex(destination.ParentStructure, destination).rep;
						e.SegmentName = destination.GetStructureName();
						throw;
					}
				}
			}

			//set data type of OBX-5
			if (destination.GetType().FullName.IndexOf("OBX") >= 0)
			{
				Varies.fixOBX5(destination, Factory);
			}
		}
Пример #23
0
 /// <summary> Returns the Primitive object at the given location.</summary>
 private static IPrimitive getPrimitive(ISegment segment, int field, int rep, int component, int subcomponent)
 {
     IType type = segment.GetField(field, rep);
     return getPrimitive(type, component, subcomponent);
 }
Пример #24
0
        /// <summary> Populates the given error segment with information from this Exception.</summary>
        public virtual void populate(ISegment errorSegment)
        {
            //make sure it's an ERR
            if (!errorSegment.GetStructureName().Equals("ERR"))
                throw new HL7Exception("Can only populate an ERR segment with an exception -- got: " + errorSegment.GetType().FullName);

            int rep = errorSegment.GetField(1).Length; //append after existing reps

            if (this.SegmentName != null)
                Terser.Set(errorSegment, 1, rep, 1, 1, this.SegmentName);

            if (this.SegmentRepetition >= 0)
                Terser.Set(errorSegment, 1, rep, 2, 1, System.Convert.ToString(this.SegmentRepetition));

            if (this.FieldPosition >= 0)
                Terser.Set(errorSegment, 1, rep, 3, 1, System.Convert.ToString(this.FieldPosition));

            Terser.Set(errorSegment, 1, rep, 4, 1, System.Convert.ToString(this.errCode));
            Terser.Set(errorSegment, 1, rep, 4, 3, "hl70357");
            Terser.Set(errorSegment, 1, rep, 4, 5, this.Message);

            //try to get error condition text
            try
            {
                System.String desc = TableRepository.Instance.getDescription(357, System.Convert.ToString(this.errCode));
                Terser.Set(errorSegment, 1, rep, 4, 2, desc);
            }
            catch (LookupException e)
            {
                ourLog.Debug("Warning: LookupException getting error condition text (are we connected to a TableRepository?)", e);
            }
        }
Пример #25
0
        /// <summary>
        /// Sets the data type of field 5 in the given OBX segment to the value of OBX-2.  The argument
        /// is a Segment as opposed to a particular OBX because it is meant to work with any version.
        /// <para>
        /// Note that if no value is present in OBX-2, or an invalid value is present in
        /// OBX-2, this method will throw an error.This behaviour can be corrected by using the
        /// <see cref="ParserOptions.DefaultObx2Type"/> and <see cref="ParserOptions.InvalidObx2Type"/>.
        /// </para>
        /// </summary>
        /// <param name="segment"><see cref="ISegment"/> instance.</param>
        /// <param name="factory"><see cref="IModelClassFactory"/> to be used.</param>
        /// <param name="parserOptions"><see cref="ParserOptions"/> to be used.</param>
        /// <exception cref="HL7Exception">If no value is present in OBX-2.</exception>
        /// <exception cref="HL7Exception">If an invalid value is present in OBX-2.</exception>
        public static void FixOBX5(ISegment segment, IModelClassFactory factory, ParserOptions parserOptions)
        {
            try
            {
                // get unqualified class name
                var obx2 = (IPrimitive)segment.GetField(2, 0);

                foreach (var repetition in segment.GetField(5))
                {
                    var v = (Varies)repetition;
                    SetObx2Fallback(obx2, segment, parserOptions);

                    if (obx2.Value == null)
                    {
                        if (v.Data != null)
                        {
                            if (!(v.Data is IPrimitive) || ((IPrimitive)v.Data).Value != null)
                            {
                                throw new HL7Exception(
                                          "OBX-5 is valued, but OBX-2 is not.  A datatype for OBX-5 must be specified using OBX-2.",
                                          ErrorCode.REQUIRED_FIELD_MISSING);
                            }
                        }
                    }
                    else
                    {
                        UseDTInsteadOfDTMForEarlierVersionsOfHL7(segment, obx2);

                        var type = GetObx5Type(obx2, segment, factory, parserOptions);

                        if (type == null)
                        {
                            var obx1         = (IPrimitive)segment.GetField(1, 0);
                            var hl7Exception = new HL7Exception(
                                $"'{obx2.Value}' in record {obx1.Value} is invalid for version {segment.Message.Version}");

                            hl7Exception.SegmentName   = ((AbstractSegment)segment).GetStructureName();
                            hl7Exception.FieldPosition = 2;

                            throw hl7Exception;
                        }

                        try
                        {
                            var constructor = type.GetConstructor(new[] { typeof(IMessage), typeof(string) });
                            v.Data = (IType)constructor.Invoke(new object[] { v.Message, v.Description });
                        }
                        catch (NullReferenceException)
                        {
                            var constructor = type.GetConstructor(new[] { typeof(IMessage) });
                            v.Data = (IType)constructor.Invoke(new object[] { v.Message });
                        }
                    }
                }
            }
            catch (HL7Exception e)
            {
                throw e;
            }
            catch (Exception e)
            {
                throw new HL7Exception(
                          $"{e.GetType().FullName} trying to set data type of OBX-5",
                          ErrorCode.APPLICATION_INTERNAL_ERROR,
                          e);
            }
        }