예제 #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(Segment 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);
                Type[]        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 NuGenHL7Exception("DOMException encoding Segment: ", NuGenHL7Exception.APPLICATION_INTERNAL_ERROR, e);
                        }
                        hasValue = true;
                    }
                }
            }
            return(hasValue);
        }
예제 #2
0
        /// <summary> Formats a Message object into an HL7 message string using this parser's
        /// default encoding ("VB").
        /// </summary>
        /// <throws>  HL7Exception if the data fields in the message do not permit encoding </throws>
        /// <summary>      (e.g. required fields are null)
        /// </summary>
        protected internal override System.String doEncode(Message source)
        {
            //get encoding characters ...
            Segment msh = (Segment)source.get_Renamed("MSH");

            System.String fieldSepString = Terser.get_Renamed(msh, 1, 0, 1, 1);

            if (fieldSepString == null)
            {
                throw new NuGenHL7Exception("Can't encode message: MSH-1 (field separator) is missing");
            }

            char fieldSep = '|';

            if (fieldSepString != null && fieldSepString.Length > 0)
            {
                fieldSep = fieldSepString[0];
            }

            System.String encCharString = Terser.get_Renamed(msh, 2, 0, 1, 1);

            if (encCharString == null)
            {
                throw new NuGenHL7Exception("Can't encode message: MSH-2 (encoding characters) is missing");
            }

            if (encCharString.Length != 4)
            {
                throw new NuGenHL7Exception("Encoding characters '" + encCharString + "' invalid -- must be 4 characters", NuGenHL7Exception.DATA_TYPE_ERROR);
            }
            NuGenEncodingCharacters en = new NuGenEncodingCharacters(fieldSep, encCharString);

            //pass down to group encoding method which will operate recursively on children ...
            return(encode((Group)source, en));
        }
예제 #3
0
        /// <summary> Populates the given Segment object with data from the given XML Element.</summary>
        /// <throws>  HL7Exception if the XML Element does not have the correct name and structure </throws>
        /// <summary>      for the given Segment, or if there is an error while setting individual field values.
        /// </summary>
        public virtual void  parse(Segment segmentObject, System.Xml.XmlElement segmentElement)
        {
            SupportClass.HashSetSupport done = new SupportClass.HashSetSupport();

            System.Xml.XmlNodeList all = segmentElement.ChildNodes;
            for (int i = 0; i < all.Count; i++)
            {
                System.String elementName = all.Item(i).Name;
                if (System.Convert.ToInt16(all.Item(i).NodeType) == (short)System.Xml.XmlNodeType.Element && !done.Contains(elementName))
                {
                    done.Add(elementName);

                    int index = elementName.IndexOf('.');
                    if (index >= 0 && elementName.Length > index)
                    {
                        //properly formatted element
                        System.String fieldNumString = elementName.Substring(index + 1);
                        int           fieldNum       = System.Int32.Parse(fieldNumString);
                        parseReps(segmentObject, segmentElement, elementName, fieldNum);
                    }
                    else
                    {
                    }
                }
            }

            //set data type of OBX-5
            if (segmentObject.GetType().FullName.IndexOf("OBX") >= 0)
            {
                Varies.fixOBX5(segmentObject, Factory);
            }
        }
예제 #4
0
        /// <summary> Fills in the details of an Application Reject message, including response and
        /// error codes, and a text error message.  This is the method to override if you want
        /// to respond differently.
        /// </summary>
        public virtual void  fillDetails(Message ack)
        {
            try
            {
                //populate MSA and ERR with generic error ...
                Segment msa = (Segment)ack.get_Renamed("MSA");
                Terser.set_Renamed(msa, 1, 0, 1, 1, "AR");
                Terser.set_Renamed(msa, 3, 0, 1, 1, "No appropriate destination could be found to which this message could be routed.");
                //this is max length

                //populate ERR segment if it exists (may not depending on version)
                Structure s = ack.get_Renamed("ERR");
                if (s != null)
                {
                    Segment err = (Segment)s;
                    Terser.set_Renamed(err, 1, 0, 4, 1, "207");
                    Terser.set_Renamed(err, 1, 0, 4, 2, "Application Internal Error");
                    Terser.set_Renamed(err, 1, 0, 4, 3, "HL70357");
                }
            }
            catch (System.Exception e)
            {
                throw new NuGenApplicationException("Error trying to create Application Reject message: " + e.Message);
            }
        }
예제 #5
0
        private static NuGenTransportable makeAcceptAck(NuGenTransportable theMessage, System.String theAckCode, int theErrorCode, System.String theDescription)
        {
            Segment header = ourParser.getCriticalResponseData(theMessage.Message);
            Message out_Renamed;

            try
            {
                out_Renamed = DefaultApplication.makeACK(header);
            }
            catch (System.IO.IOException e)
            {
                throw new NuGenHL7Exception(e);
            }

            Terser t = new Terser(out_Renamed);

            t.set_Renamed("/MSA-1", theAckCode);

            //TODO: when 2.5 is available, use 2.5 fields for remaining problems
            if (theErrorCode != NuGenHL7Exception.MESSAGE_ACCEPTED)
            {
                t.set_Renamed("/MSA-3", theDescription.Substring(0, (System.Math.Min(80, theDescription.Length)) - (0)));
                t.set_Renamed("/ERR-1-4-1", System.Convert.ToString(theErrorCode));
                t.set_Renamed("/ERR-1-4-3", "HL70357");
            }

            System.String originalEncoding = ourParser.getEncoding(theMessage.Message);
            System.String ackText          = ourParser.encode(out_Renamed, originalEncoding);
            return(new NuGenTransportableImpl(ackText));
        }
예제 #6
0
 private void  parseReps(Segment 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));
     }
 }
예제 #7
0
        /// <summary> <p>Returns a minimal amount of data from a message string, including only the
        /// data needed to send a response to the remote system.  This includes the
        /// following fields:
        /// <ul><li>field separator</li>
        /// <li>encoding characters</li>
        /// <li>processing ID</li>
        /// <li>message control ID</li></ul>
        /// This method is intended for use when there is an error parsing a message,
        /// (so the Message object is unavailable) but an error message must be sent
        /// back to the remote system including some of the information in the inbound
        /// message.  This method parses only that required information, hopefully
        /// avoiding the condition that caused the original error.  The other
        /// fields in the returned MSH segment are empty.</p>
        /// </summary>
        public override Segment getCriticalResponseData(System.String message)
        {
            //try to get MSH segment
            int locStartMSH = message.IndexOf("MSH");

            if (locStartMSH < 0)
            {
                throw new NuGenHL7Exception("Couldn't find MSH segment in message: " + message, NuGenHL7Exception.SEGMENT_SEQUENCE_ERROR);
            }
            int locEndMSH = message.IndexOf('\r', locStartMSH + 1);

            if (locEndMSH < 0)
            {
                locEndMSH = message.Length;
            }
            System.String mshString = message.Substring(locStartMSH, (locEndMSH) - (locStartMSH));

            //find out what the field separator is
            char fieldSep = mshString[3];

            //get field array
            System.String[] fields = split(mshString, System.Convert.ToString(fieldSep));

            Segment msh = null;

            try
            {
                //parse required fields
                System.String   encChars      = fields[1];
                char            compSep       = encChars[0];
                System.String   messControlID = fields[9];
                System.String[] procIDComps   = split(fields[10], System.Convert.ToString(compSep));

                //fill MSH segment
                System.String version = "2.4";                 //default
                try
                {
                    version = this.getVersion(message);
                }
                catch (System.Exception)
                {
                    /* use the default */
                }

                msh = NuGenParser.makeControlMSH(version, Factory);
                Terser.set_Renamed(msh, 1, 0, 1, 1, System.Convert.ToString(fieldSep));
                Terser.set_Renamed(msh, 2, 0, 1, 1, encChars);
                Terser.set_Renamed(msh, 10, 0, 1, 1, messControlID);
                Terser.set_Renamed(msh, 11, 0, 1, 1, procIDComps[0]);
                Terser.set_Renamed(msh, 12, 0, 1, 1, version);
            }
            catch (System.Exception e)
            {
                throw new NuGenHL7Exception("Can't parse critical fields from MSH segment (" + e.GetType().FullName + ": " + e.Message + "): " + mshString, NuGenHL7Exception.REQUIRED_FIELD_MISSING, e);
            }

            return(msh);
        }
예제 #8
0
        /// <summary> Logs the given exception and creates an error message to send to the
        /// remote system.
        ///
        /// </summary>
        /// <param name="encoding">The encoding for the error message. If <code>null</code>, uses default encoding
        /// </param>
        public static System.String logAndMakeErrorMessage(System.Exception e, Segment inHeader, Parser p, System.String encoding)
        {
            // create error message ...
            System.String errorMessage = null;
            try
            {
                Message out_Renamed = NuGenDefaultApplication.makeACK(inHeader);
                Terser  t           = new Terser(out_Renamed);

                //copy required data from incoming message ...
                try
                {
                    t.set_Renamed("/MSH-10", MessageIDGenerator.Instance.NewID);
                }
                catch (System.IO.IOException ioe)
                {
                    throw new NuGenHL7Exception("Problem creating error message ID: " + ioe.Message);
                }

                //populate MSA ...
                t.set_Renamed("/MSA-1", "AE");                 //should this come from HL7Exception constructor?
                t.set_Renamed("/MSA-2", Terser.get_Renamed(inHeader, 10, 0, 1, 1));
                System.String excepMessage = e.Message;
                if (excepMessage != null)
                {
                    t.set_Renamed("/MSA-3", excepMessage.Substring(0, (System.Math.Min(80, excepMessage.Length)) - (0)));
                }

                /* Some earlier ACKs don't have ERRs, but I think we'll change this within HAPI
                 * so that there is a single ACK for each version (with an ERR). */
                //see if it's an HL7Exception (so we can get specific information) ...
                if (e.GetType().Equals(typeof(NuGenHL7Exception)))
                {
                    Segment err = (Segment)out_Renamed.get_Renamed("ERR");
                    ((NuGenHL7Exception)e).populate(err);
                }
                else
                {
                    t.set_Renamed("/ERR-1-4-1", "207");
                    t.set_Renamed("/ERR-1-4-2", "Application Internal Error");
                    t.set_Renamed("/ERR-1-4-3", "HL70357");
                }

                if (encoding != null)
                {
                    errorMessage = p.encode(out_Renamed, encoding);
                }
                else
                {
                    errorMessage = p.encode(out_Renamed);
                }
            }
            catch (System.IO.IOException ioe)
            {
                throw new NuGenHL7Exception("IOException creating error response message: " + ioe.Message, NuGenHL7Exception.APPLICATION_INTERNAL_ERROR);
            }
            return(errorMessage);
        }
예제 #9
0
        /// <summary> Creates an ACK message with the minimum required information from an inbound message.
        /// Optional fields can be filled in afterwards, before the message is returned.  Pleaase
        /// note that MSH-10, the outbound message control ID, is also set using the class
        /// <code>Genetibase.NuGenHL7.util.MessageIDGenerator</code>.  Also note that the ACK messages returned
        /// is the same version as the version stated in the inbound MSH if there is a generic ACK for that
        /// version, otherwise a version 2.4 ACK is returned. MSA-1 is set to AA by default.
        ///
        /// </summary>
        /// <param name="inboundHeader">the MSH segment if the inbound message
        /// </param>
        /// <throws>  IOException if there is a problem reading or writing the message ID file </throws>
        /// <throws>  DataTypeException if there is a problem setting ACK values </throws>
        public static Message makeACK(Segment inboundHeader)
        {
            if (!inboundHeader.getName().Equals("MSH"))
            {
                throw new NuGenHL7Exception("Need an MSH segment to create a response ACK (got " + inboundHeader.getName() + ")");
            }

            //make ACK of correct version
            System.String version = null;
            try
            {
                version = Terser.get_Renamed(inboundHeader, 12, 0, 1, 1);
            }
            catch (NuGenHL7Exception)
            {
                /* proceed with null */
            }
            if (version == null)
            {
                version = "2.4";
            }

            System.String ackClassName = SourceGenerator.getVersionPackageName(version) + "message.ACK";

            Message out_Renamed = null;

            try
            {
                System.Type ackClass = System.Type.GetType(ackClassName);
                out_Renamed = (Message)System.Activator.CreateInstance(ackClass);
            }
            catch (System.Exception e)
            {
                throw new NuGenHL7Exception("Can't instantiate ACK of class " + ackClassName + ": " + e.GetType().FullName);
            }
            Terser terser = new Terser(out_Renamed);

            //populate outbound MSH using data from inbound message ...
            Segment outHeader = (Segment)out_Renamed.get_Renamed("MSH");

            fillResponseHeader(inboundHeader, outHeader);

            terser.set_Renamed("/MSH-9", "ACK");
            terser.set_Renamed("/MSH-12", version);
            terser.set_Renamed("/MSA-1", "AA");
            terser.set_Renamed("/MSA-2", Genetibase.NuGenHL7.util.NuGenTerser.get_Renamed(inboundHeader, 10, 0, 1, 1));

            return(out_Renamed);
        }
예제 #10
0
        public static System.String encode(Segment source, NuGenEncodingCharacters encodingChars)
        {
            System.Text.StringBuilder result = new System.Text.StringBuilder();
            result.Append(source.getName());
            result.Append(encodingChars.FieldSeparator);

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

            if (isDelimDefSegment(source.getName()))
            {
                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
                {
                    Type[] reps = source.getField(i);
                    for (int j = 0; j < reps.Length; j++)
                    {
                        System.String fieldText = encode(reps[j], encodingChars);
                        //if this is MSH-2, then it shouldn't be escaped, so unescape it again
                        if (isDelimDefSegment(source.getName()) && i == 2)
                        {
                            fieldText = NuGenEscape.unescape(fieldText, encodingChars);
                        }
                        result.Append(fieldText);
                        if (j < reps.Length - 1)
                        {
                            result.Append(encodingChars.RepetitionSeparator);
                        }
                    }
                }
                catch (NuGenHL7Exception)
                {
                }
                result.Append(encodingChars.FieldSeparator);
            }

            //strip trailing delimiters ...
            return(stripExtraDelimiters(result.ToString(), encodingChars.FieldSeparator));
        }
예제 #11
0
        private void  parse(SupportClass.Tokenizer tok, Message message, StructRef root, NuGenEncodingCharacters ec)
        {
            Terser t = new Terser(message);

            lock (root)
            {
                StructRef ref_Renamed = root.getSuccessor("MSH");

                int     field   = 0;
                Segment segment = null;
                int[]   fields  = new int[0];

                while (tok.HasMoreTokens())
                {
                    System.String token = tok.NextToken();
                    if (token[0] == ec.FieldSeparator)
                    {
                        field++;
                    }
                    else if (token[0] == ourSegmentSeparator)
                    {
                        field = 0;
                    }
                    else if (field == 0)
                    {
                        StructRef newref = drill(ref_Renamed, token);
                        if (newref == null)
                        {
                            segment = null;
                            fields  = new int[0];
                        }
                        else
                        {
                            ref_Renamed = newref;
                            segment     = t.getSegment(ref_Renamed.FullPath);
                            fields      = ref_Renamed.Fields;
                        }
                    }
                    else if (segment != null && System.Array.BinarySearch(fields, (System.Object)field) >= 0)
                    {
                        parse(token, segment, field, ec);
                    }
                }
                root.reset();
            }
        }
예제 #12
0
        /// <summary> <p>Returns a minimal amount of data from a message string, including only the
        /// data needed to send a response to the remote system.  This includes the
        /// following fields:
        /// <ul><li>field separator</li>
        /// <li>encoding characters</li>
        /// <li>processing ID</li>
        /// <li>message control ID</li></ul>
        /// This method is intended for use when there is an error parsing a message,
        /// (so the Message object is unavailable) but an error message must be sent
        /// back to the remote system including some of the information in the inbound
        /// message.  This method parses only that required information, hopefully
        /// avoiding the condition that caused the original error.</p>
        /// </summary>
        public override Segment getCriticalResponseData(System.String message)
        {
            System.String version      = getVersion(message);
            Segment       criticalData = NuGenParser.makeControlMSH(version, Factory);

            Terser.set_Renamed(criticalData, 1, 0, 1, 1, parseLeaf(message, "MSH.1", 0));
            Terser.set_Renamed(criticalData, 2, 0, 1, 1, parseLeaf(message, "MSH.2", 0));
            Terser.set_Renamed(criticalData, 10, 0, 1, 1, parseLeaf(message, "MSH.10", 0));
            System.String procID = parseLeaf(message, "MSH.11", 0);
            if (procID == null || procID.Length == 0)
            {
                procID = parseLeaf(message, "PT.1", message.IndexOf("MSH.11"));
                //this field is a composite in later versions
            }
            Terser.set_Renamed(criticalData, 11, 0, 1, 1, procID);

            return(criticalData);
        }
예제 #13
0
        /// <summary> Ensures that there is an empty repetition of the underlying message Structure.  </summary>
        /// <returns>s true if successful, false if structure is non-repeating and full.
        /// </returns>
        private bool prepEmptyInstance()
        {
            bool success = false;

            if (this.currSegment == null || (this.repeating && this.currSegmentFull))
            {
                int numExisting = parent.getAll(this.name).Length;
                this.currSegment     = (Segment)parent.get_Renamed(this.name, numExisting);              //get next rep
                this.currSegmentFull = false;
                success = true;
            }
            else if (!this.currSegmentFull)
            {
                success = true;
            }

            return(success);
        }
예제 #14
0
        /// <summary> Creates a version-specific MSH object and returns it as a version-independent
        /// MSH interface.
        /// throws HL7Exception if there is a problem, e.g. invalid version, code not available
        /// for given version.
        /// </summary>
        public static Segment makeControlMSH(System.String version, NuGenModelClassFactory factory)
        {
            Segment msh = null;

            try
            {
                Message dummy = (Message)GenericMessage.getGenericMessageClass(version).GetConstructor(new System.Type[] { typeof(NuGenModelClassFactory) }).Invoke(new System.Object[] { factory });

                System.Type[]   constructorParamTypes = new System.Type[] { typeof(Group), typeof(NuGenModelClassFactory) };
                System.Object[] constructorParamArgs  = new System.Object[] { dummy, factory };
                System.Type     c = factory.getSegmentClass("MSH", version);
                System.Reflection.ConstructorInfo constructor = c.GetConstructor(constructorParamTypes);
                msh = (Segment)constructor.Invoke(constructorParamArgs);
            }
            catch (System.Exception e)
            {
                throw new NuGenHL7Exception("Couldn't create MSH for version " + version + " (does your classpath include this version?) ... ", NuGenHL7Exception.APPLICATION_INTERNAL_ERROR, e);
            }
            return(msh);
        }
예제 #15
0
        /// <seealso cref="Genetibase.NuGenHL7.parser.Parser.doParse(java.lang.String, java.lang.String)">
        /// </seealso>
        protected internal override Message doParse(System.String message, System.String version)
        {
            Message result = null;

            char fieldSep = message[3];
            NuGenEncodingCharacters ec = new NuGenEncodingCharacters(fieldSep, message.Substring(4, (8) - (4)));

            SupportClass.Tokenizer tok = new SupportClass.Tokenizer(message.Substring(4), System.Convert.ToString(new char[] { fieldSep, ourSegmentSeparator }), true);

            System.String[] mshFields = getMSHFields(tok, fieldSep);
            System.Object[] structure = getStructure(mshFields[8], ec.ComponentSeparator);

            StructRef root = (StructRef)myEventGuideMap[structure[0]];

            if (root == null)
            {
                result = myPipeParser.parse(message);
            }
            else
            {
                int csIndex = mshFields[11].IndexOf((System.Char)ec.ComponentSeparator);
                result = instantiateMessage((System.String)structure[1], version, ((System.Boolean)structure[2]));

                StructRef mshRef = null;
                lock (root)
                {
                    mshRef = root.getSuccessor("MSH");
                    root.reset();
                }
                Segment msh = (Segment)result.get_Renamed("MSH");
                for (int i = 0; i < mshRef.Fields.Length; i++)
                {
                    int fieldNum = mshRef.Fields[i];
                    parse(mshFields[fieldNum - 1], msh, fieldNum, ec);
                }

                parse(tok, result, root, ec);
            }

            return(result);
        }
예제 #16
0
        /// <summary> Populates certain required fields in a response message header, using
        /// information from the corresponding inbound message.  The current time is
        /// used for the message time field, and <code>MessageIDGenerator</code> is
        /// used to create a unique message ID.  Version and message type fields are
        /// not populated.
        /// </summary>
        public static void  fillResponseHeader(Segment inbound, Segment outbound)
        {
            if (!inbound.getName().Equals("MSH") || !outbound.getName().Equals("MSH"))
            {
                throw new NuGenHL7Exception("Need MSH segments.  Got " + inbound.getName() + " and " + outbound.getName());
            }

            //get MSH data from incoming message ...
            System.String encChars = Terser.get_Renamed(inbound, 2, 0, 1, 1);
            System.String fieldSep = Terser.get_Renamed(inbound, 1, 0, 1, 1);
            System.String procID   = Terser.get_Renamed(inbound, 11, 0, 1, 1);

            //populate outbound MSH using data from inbound message ...
            Terser.set_Renamed(outbound, 2, 0, 1, 1, encChars);
            Terser.set_Renamed(outbound, 1, 0, 1, 1, fieldSep);
            System.Globalization.GregorianCalendar now = new System.Globalization.GregorianCalendar();
            SupportClass.CalendarManager.manager.SetDateTime(now, System.DateTime.Now);
            Terser.set_Renamed(outbound, 7, 0, 1, 1, CommonTS.toHl7TSFormat(now));
            Terser.set_Renamed(outbound, 10, 0, 1, 1, MessageIDGenerator.Instance.NewID);
            Terser.set_Renamed(outbound, 11, 0, 1, 1, procID);
        }
예제 #17
0
        /// <summary> Populates the given error segment with information from this Exception.</summary>
        public virtual void  populate(Segment errorSegment)
        {
            //make sure it's an ERR
            if (!errorSegment.getName().Equals("ERR"))
            {
                throw new NuGenHL7Exception("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_Renamed(errorSegment, 1, rep, 1, 1, this.SegmentName);
            }

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

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

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

            //try to get error condition text
            try
            {
                System.String desc = NuGenTableRepository.Instance.getDescription(357, System.Convert.ToString(this.errCode));
                Terser.set_Renamed(errorSegment, 1, rep, 4, 2, desc);
            }
            catch (NuGenLookupException)
            {
            }
        }
예제 #18
0
        private void  parse(System.String field, Segment segment, int num, NuGenEncodingCharacters ec)
        {
            if (field != null)
            {
                int  rep          = 0;
                int  component    = 1;
                int  subcomponent = 1;
                Type type         = segment.getField(num, rep);

                System.String delim = System.Convert.ToString(new char[] { ec.RepetitionSeparator, ec.ComponentSeparator, ec.SubcomponentSeparator });
                for (SupportClass.Tokenizer tok = new SupportClass.Tokenizer(field, delim, true); tok.HasMoreTokens();)
                {
                    System.String token = tok.NextToken();
                    char          c     = token[0];
                    if (c == ec.RepetitionSeparator)
                    {
                        rep++;
                        component    = 1;
                        subcomponent = 1;
                        type         = segment.getField(num, rep);
                    }
                    else if (c == ec.ComponentSeparator)
                    {
                        component++;
                        subcomponent = 1;
                    }
                    else if (c == ec.SubcomponentSeparator)
                    {
                        subcomponent++;
                    }
                    else
                    {
                        Primitive p = Terser.getPrimitive(type, component, subcomponent);
                        p.Value = token;
                    }
                }
            }
        }
예제 #19
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(Segment 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);
				Type[] 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 NuGenHL7Exception("DOMException encoding Segment: ", NuGenHL7Exception.APPLICATION_INTERNAL_ERROR, e);
						}
						hasValue = true;
					}
				}
			}
			return hasValue;
		}
예제 #20
0
		/// <summary> Populates the given Segment object with data from the given XML Element.</summary>
		/// <throws>  HL7Exception if the XML Element does not have the correct name and structure </throws>
		/// <summary>      for the given Segment, or if there is an error while setting individual field values.
		/// </summary>
		public virtual void  parse(Segment segmentObject, System.Xml.XmlElement segmentElement)
		{
			SupportClass.HashSetSupport done = new SupportClass.HashSetSupport();
			
			System.Xml.XmlNodeList all = segmentElement.ChildNodes;
			for (int i = 0; i < all.Count; i++)
			{
				System.String elementName = all.Item(i).Name;
				if (System.Convert.ToInt16(all.Item(i).NodeType) == (short) System.Xml.XmlNodeType.Element && !done.Contains(elementName))
				{
					done.Add(elementName);
					
					int index = elementName.IndexOf('.');
					if (index >= 0 && elementName.Length > index)
					{
						//properly formatted element
						System.String fieldNumString = elementName.Substring(index + 1);
						int fieldNum = System.Int32.Parse(fieldNumString);
						parseReps(segmentObject, segmentElement, elementName, fieldNum);
					}
					else
					{
					}
				}
			}
			
			//set data type of OBX-5        
			if (segmentObject.GetType().FullName.IndexOf("OBX") >= 0)
			{
				Varies.fixOBX5(segmentObject, Factory);
			}
		}
예제 #21
0
		public static System.String encode(Segment source, NuGenEncodingCharacters encodingChars)
		{
			System.Text.StringBuilder result = new System.Text.StringBuilder();
			result.Append(source.getName());
			result.Append(encodingChars.FieldSeparator);
			
			//start at field 2 for MSH segment because field 1 is the field delimiter
			int startAt = 1;
			if (isDelimDefSegment(source.getName()))
				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
				{
					Type[] reps = source.getField(i);
					for (int j = 0; j < reps.Length; j++)
					{
						System.String fieldText = encode(reps[j], encodingChars);
						//if this is MSH-2, then it shouldn't be escaped, so unescape it again
						if (isDelimDefSegment(source.getName()) && i == 2)
							fieldText = NuGenEscape.unescape(fieldText, encodingChars);
						result.Append(fieldText);
						if (j < reps.Length - 1)
							result.Append(encodingChars.RepetitionSeparator);
					}
				}
				catch (NuGenHL7Exception)
				{
				}
				result.Append(encodingChars.FieldSeparator);
			}
			
			//strip trailing delimiters ...
			return stripExtraDelimiters(result.ToString(), encodingChars.FieldSeparator);
		}
예제 #22
0
		/// <summary>Returns the expected XML element name for the given child of the given Segment </summary>
		private System.String makeElementName(Segment s, int child)
		{
			return s.getName() + "." + child;
		}
예제 #23
0
 /// <summary>Returns the expected XML element name for the given child of the given Segment </summary>
 private System.String makeElementName(Segment s, int child)
 {
     return(s.getName() + "." + child);
 }
예제 #24
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(Segment destination, System.String segment, NuGenEncodingCharacters encodingChars)
		{
			int fieldOffset = 0;
			if (isDelimDefSegment(destination.getName()))
			{
				fieldOffset = 1;
				//set field 1 to fourth character of string
				Terser.set_Renamed(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));
				
				//MSH-2 will get split incorrectly so we have to fudge it ...
				bool isMSH2 = isDelimDefSegment(destination.getName()) && 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);
						//parse(destination.getField(i + fieldOffset, j), reps[j], encodingChars, false);
						
						Type field = destination.getField(i + fieldOffset, j);
						if (isMSH2)
						{
							Terser.getPrimitive(field, 1, 1).Value = reps[j];
						}
						else
						{
							parse(field, reps[j], encodingChars);
						}
					}
					catch (NuGenHL7Exception e)
					{
						//set the field location and throw again ...
						e.FieldPosition = i;
						e.SegmentRepetition = MessageIterator.getIndex(destination.Parent, destination).rep;
						e.SegmentName = destination.getName();
						throw e;
					}
				}
			}
			
			//set data type of OBX-5
			if (destination.GetType().FullName.IndexOf("OBX") >= 0)
			{
				Varies.fixOBX5(destination, Factory);
			}
		}
예제 #25
0
		/// <summary> Logs the given exception and creates an error message to send to the
		/// remote system.
		/// 
		/// </summary>
		/// <param name="encoding">The encoding for the error message. If <code>null</code>, uses default encoding 
		/// </param>
		public static System.String logAndMakeErrorMessage(System.Exception e, Segment inHeader, Parser p, System.String encoding)
		{
			
			
			// create error message ...
			System.String errorMessage = null;
			try
			{
				Message out_Renamed = NuGenDefaultApplication.makeACK(inHeader);
				Terser t = new Terser(out_Renamed);
				
				//copy required data from incoming message ...
				try
				{
					t.set_Renamed("/MSH-10", MessageIDGenerator.Instance.NewID);
				}
				catch (System.IO.IOException ioe)
				{
					throw new NuGenHL7Exception("Problem creating error message ID: " + ioe.Message);
				}
				
				//populate MSA ...
				t.set_Renamed("/MSA-1", "AE"); //should this come from HL7Exception constructor?
				t.set_Renamed("/MSA-2", Terser.get_Renamed(inHeader, 10, 0, 1, 1));
				System.String excepMessage = e.Message;
				if (excepMessage != null)
					t.set_Renamed("/MSA-3", excepMessage.Substring(0, (System.Math.Min(80, excepMessage.Length)) - (0)));
				
				/* Some earlier ACKs don't have ERRs, but I think we'll change this within HAPI
				so that there is a single ACK for each version (with an ERR). */
				//see if it's an HL7Exception (so we can get specific information) ...
				if (e.GetType().Equals(typeof(NuGenHL7Exception)))
				{
					Segment err = (Segment) out_Renamed.get_Renamed("ERR");
					((NuGenHL7Exception) e).populate(err);
				}
				else
				{
					t.set_Renamed("/ERR-1-4-1", "207");
					t.set_Renamed("/ERR-1-4-2", "Application Internal Error");
					t.set_Renamed("/ERR-1-4-3", "HL70357");
				}
				
				if (encoding != null)
				{
					errorMessage = p.encode(out_Renamed, encoding);
				}
				else
				{
					errorMessage = p.encode(out_Renamed);
				}
			}
			catch (System.IO.IOException ioe)
			{
				throw new NuGenHL7Exception("IOException creating error response message: " + ioe.Message, NuGenHL7Exception.APPLICATION_INTERNAL_ERROR);
			}
			return errorMessage;
		}
예제 #26
0
        public static void  Main(System.String[] args)
        {
            if (args.Length != 1)
            {
                System.Console.Out.WriteLine("Usage: XMLParser pipe_encoded_file");
                System.Environment.Exit(1);
            }

            //read and parse message from file
            try
            {
                NuGenPipeParser    parser      = new NuGenPipeParser();
                System.IO.FileInfo messageFile = new System.IO.FileInfo(args[0]);
                long fileLength          = SupportClass.FileLength(messageFile);
                System.IO.StreamReader r = new System.IO.StreamReader(messageFile.FullName, System.Text.Encoding.Default);
                char[] cbuf = new char[(int)fileLength];
                System.Console.Out.WriteLine("Reading message file ... " + r.Read((System.Char[])cbuf, 0, cbuf.Length) + " of " + fileLength + " chars");
                r.Close();
                System.String messString = System.Convert.ToString(cbuf);
                Message       mess       = parser.parse(messString);
                System.Console.Out.WriteLine("Got message of type " + mess.GetType().FullName);

                Genetibase.NuGenHL7.parser.NuGenXMLParser xp = new AnonymousClassXMLParser();

                //loop through segment children of message, encode, print to console
                System.String[] structNames = mess.Names;
                for (int i = 0; i < structNames.Length; i++)
                {
                    Structure[] reps = mess.getAll(structNames[i]);
                    for (int j = 0; j < reps.Length; j++)
                    {
                        if (typeof(Segment).IsAssignableFrom(reps[j].GetType()))
                        {
                            //ignore groups
                            System.Xml.XmlDocument docBuilder = new System.Xml.XmlDocument();
                            System.Xml.XmlDocument doc        = new System.Xml.XmlDocument();                      //new doc for each segment
                            System.Xml.XmlElement  root       = doc.CreateElement(reps[j].GetType().FullName);
                            doc.AppendChild(root);
                            xp.encode((Segment)reps[j], root);
                            System.IO.StringWriter out_Renamed = new System.IO.StringWriter();
                            System.Console.Out.WriteLine("Segment " + reps[j].GetType().FullName + ": \r\n" + out_Renamed.ToString());

                            System.Type[]   segmentConstructTypes = new System.Type[] { typeof(Message) };
                            System.Object[] segmentConstructArgs  = new System.Object[] { null };
                            Segment         s = (Segment)reps[j].GetType().GetConstructor(segmentConstructTypes).Invoke(segmentConstructArgs);
                            xp.parse(s, root);
                            System.Xml.XmlDocument doc2  = new System.Xml.XmlDocument();
                            System.Xml.XmlElement  root2 = doc2.CreateElement(s.GetType().FullName);
                            doc2.AppendChild(root2);
                            xp.encode(s, root2);
                            System.IO.StringWriter out2 = new System.IO.StringWriter();

                            if (out2.ToString().Equals(out_Renamed.ToString()))
                            {
                                System.Console.Out.WriteLine("Re-encode OK");
                            }
                            else
                            {
                                System.Console.Out.WriteLine("Warning: XML different after parse and re-encode: \r\n" + out2.ToString());
                            }
                        }
                    }
                }
            }
            catch (System.Exception e)
            {
                SupportClass.WriteStackTrace(e, Console.Error);
            }
        }
		/// <summary> Populates certain required fields in a response message header, using 
		/// information from the corresponding inbound message.  The current time is 
		/// used for the message time field, and <code>MessageIDGenerator</code> is 
		/// used to create a unique message ID.  Version and message type fields are 
		/// not populated.  
		/// </summary>
		public static void  fillResponseHeader(Segment inbound, Segment outbound)
		{
			if (!inbound.getName().Equals("MSH") || !outbound.getName().Equals("MSH"))
				throw new NuGenHL7Exception("Need MSH segments.  Got " + inbound.getName() + " and " + outbound.getName());
			
			//get MSH data from incoming message ...        
			System.String encChars = Terser.get_Renamed(inbound, 2, 0, 1, 1);
			System.String fieldSep = Terser.get_Renamed(inbound, 1, 0, 1, 1);
			System.String procID = Terser.get_Renamed(inbound, 11, 0, 1, 1);
			
			//populate outbound MSH using data from inbound message ...                     
			Terser.set_Renamed(outbound, 2, 0, 1, 1, encChars);
			Terser.set_Renamed(outbound, 1, 0, 1, 1, fieldSep);
			System.Globalization.GregorianCalendar now = new System.Globalization.GregorianCalendar();
			SupportClass.CalendarManager.manager.SetDateTime(now, System.DateTime.Now);
			Terser.set_Renamed(outbound, 7, 0, 1, 1, CommonTS.toHl7TSFormat(now));
			Terser.set_Renamed(outbound, 10, 0, 1, 1, MessageIDGenerator.Instance.NewID);
			Terser.set_Renamed(outbound, 11, 0, 1, 1, procID);
		}
		/// <summary> Creates an ACK message with the minimum required information from an inbound message.  
		/// Optional fields can be filled in afterwards, before the message is returned.  Pleaase   
		/// note that MSH-10, the outbound message control ID, is also set using the class 
		/// <code>Genetibase.NuGenHL7.util.MessageIDGenerator</code>.  Also note that the ACK messages returned
		/// is the same version as the version stated in the inbound MSH if there is a generic ACK for that
		/// version, otherwise a version 2.4 ACK is returned. MSA-1 is set to AA by default.  
		/// 
		/// </summary>
		/// <param name="inboundHeader">the MSH segment if the inbound message
		/// </param>
		/// <throws>  IOException if there is a problem reading or writing the message ID file </throws>
		/// <throws>  DataTypeException if there is a problem setting ACK values </throws>
		public static Message makeACK(Segment inboundHeader)
		{
			if (!inboundHeader.getName().Equals("MSH"))
				throw new NuGenHL7Exception("Need an MSH segment to create a response ACK (got " + inboundHeader.getName() + ")");
			
			//make ACK of correct version
			System.String version = null;
			try
			{
				version = Terser.get_Renamed(inboundHeader, 12, 0, 1, 1);
			}
			catch (NuGenHL7Exception)
			{
				/* proceed with null */
			}
			if (version == null)
				version = "2.4";
			
			System.String ackClassName = SourceGenerator.getVersionPackageName(version) + "message.ACK";
			
			Message out_Renamed = null;
			try
			{
				System.Type ackClass = System.Type.GetType(ackClassName);
				out_Renamed = (Message) System.Activator.CreateInstance(ackClass);
			}
			catch (System.Exception e)
			{
				throw new NuGenHL7Exception("Can't instantiate ACK of class " + ackClassName + ": " + e.GetType().FullName);
			}
			Terser terser = new Terser(out_Renamed);
			
			//populate outbound MSH using data from inbound message ...             
			Segment outHeader = (Segment) out_Renamed.get_Renamed("MSH");
			fillResponseHeader(inboundHeader, outHeader);
			
			terser.set_Renamed("/MSH-9", "ACK");
			terser.set_Renamed("/MSH-12", version);
			terser.set_Renamed("/MSA-1", "AA");
			terser.set_Renamed("/MSA-2", Genetibase.NuGenHL7.util.NuGenTerser.get_Renamed(inboundHeader, 10, 0, 1, 1));
			
			return out_Renamed;
		}
예제 #29
0
		private void  parseReps(Segment 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));
			}
		}
예제 #30
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(Segment destination, System.String segment, NuGenEncodingCharacters encodingChars)
        {
            int fieldOffset = 0;

            if (isDelimDefSegment(destination.getName()))
            {
                fieldOffset = 1;
                //set field 1 to fourth character of string
                Terser.set_Renamed(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));

                //MSH-2 will get split incorrectly so we have to fudge it ...
                bool isMSH2 = isDelimDefSegment(destination.getName()) && 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);
                        //parse(destination.getField(i + fieldOffset, j), reps[j], encodingChars, false);

                        Type field = destination.getField(i + fieldOffset, j);
                        if (isMSH2)
                        {
                            Terser.getPrimitive(field, 1, 1).Value = reps[j];
                        }
                        else
                        {
                            parse(field, reps[j], encodingChars);
                        }
                    }
                    catch (NuGenHL7Exception e)
                    {
                        //set the field location and throw again ...
                        e.FieldPosition     = i;
                        e.SegmentRepetition = MessageIterator.getIndex(destination.Parent, destination).rep;
                        e.SegmentName       = destination.getName();
                        throw e;
                    }
                }
            }

            //set data type of OBX-5
            if (destination.GetType().FullName.IndexOf("OBX") >= 0)
            {
                Varies.fixOBX5(destination, Factory);
            }
        }
예제 #31
0
		/// <summary> Populates the given error segment with information from this Exception.</summary>
		public virtual void  populate(Segment errorSegment)
		{
			//make sure it's an ERR
			if (!errorSegment.getName().Equals("ERR"))
				throw new NuGenHL7Exception("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_Renamed(errorSegment, 1, rep, 1, 1, this.SegmentName);
			
			if (this.SegmentRepetition >= 0)
				Terser.set_Renamed(errorSegment, 1, rep, 2, 1, System.Convert.ToString(this.SegmentRepetition));
			
			if (this.FieldPosition >= 0)
				Terser.set_Renamed(errorSegment, 1, rep, 3, 1, System.Convert.ToString(this.FieldPosition));
			
			Terser.set_Renamed(errorSegment, 1, rep, 4, 1, System.Convert.ToString(this.errCode));
			Terser.set_Renamed(errorSegment, 1, rep, 4, 3, "hl70357");
			Terser.set_Renamed(errorSegment, 1, rep, 4, 5, this.Message);
			
			//try to get error condition text
			try
			{
				System.String desc = NuGenTableRepository.Instance.getDescription(357, System.Convert.ToString(this.errCode));
				Terser.set_Renamed(errorSegment, 1, rep, 4, 2, desc);
			}
			catch (NuGenLookupException)
			{

			}
		}
예제 #32
0
		private void  parse(System.String field, Segment segment, int num, NuGenEncodingCharacters ec)
		{
			if (field != null)
			{
				int rep = 0;
				int component = 1;
				int subcomponent = 1;
				Type type = segment.getField(num, rep);
				
				System.String delim = System.Convert.ToString(new char[]{ec.RepetitionSeparator, ec.ComponentSeparator, ec.SubcomponentSeparator});
				for (SupportClass.Tokenizer tok = new SupportClass.Tokenizer(field, delim, true); tok.HasMoreTokens(); )
				{
					System.String token = tok.NextToken();
					char c = token[0];
					if (c == ec.RepetitionSeparator)
					{
						rep++;
						component = 1;
						subcomponent = 1;
						type = segment.getField(num, rep);
					}
					else if (c == ec.ComponentSeparator)
					{
						component++;
						subcomponent = 1;
					}
					else if (c == ec.SubcomponentSeparator)
					{
						subcomponent++;
					}
					else
					{
						Primitive p = Terser.getPrimitive(type, component, subcomponent);
						p.Value = token;
					}
				}
			}
		}
예제 #33
0
		/// <summary> Ensures that there is an empty repetition of the underlying message Structure.  </summary>
		/// <returns>s true if successful, false if structure is non-repeating and full. 
		/// </returns>
		private bool prepEmptyInstance()
		{
			bool success = false;
			
			if (this.currSegment == null || (this.repeating && this.currSegmentFull))
			{
				int numExisting = parent.getAll(this.name).Length;
				this.currSegment = (Segment) parent.get_Renamed(this.name, numExisting); //get next rep            
				this.currSegmentFull = false;
				success = true;
			}
			else if (!this.currSegmentFull)
			{
				success = true;
			}
			
			return success;
		}