Example #1
0
        static void Main(string[] args)
        {
            string inputFilename    = args[0];
            string outputFilename   = args[1];
            string isaControlNumber = args.Length > 2 ? args[2] : "999";
            string gsControlNumber  = args.Length > 3 ? args[3] : "99";

            var service = new X12AcknowledgmentService();

            using (FileStream fs = new FileStream(inputFilename, FileMode.Open, FileAccess.Read))
            {
                using (X12StreamReader reader = new X12StreamReader(fs, Encoding.UTF8))
                {
                    var firstTrans = reader.ReadNextTransaction();
                    if (reader.LastTransactionCode == "837")
                    {
                        if (reader.TransactionContainsSegment(firstTrans.Transactions[0], "SV2"))
                        {
                            service = new InstitutionalClaimAcknowledgmentService();
                        }
                        if (reader.TransactionContainsSegment(firstTrans.Transactions[0], "SV1"))
                        {
                            service = new X12AcknowledgmentService(new ProfessionalClaimSpecificationFinder());
                        }
                    }
                }
            }

            using (FileStream fs = new FileStream(inputFilename, FileMode.Open, FileAccess.Read))
            {
                // Create aknowledgements and identify errors
                var responses = service.AcknowledgeTransactions(fs);

                // Change any acknowledgment codes here to reject transactions with errors
                // CUSTOM BUSINESS LOGIC HERE

                // Transform to outbound interchange for serialization
                var interchange = new Interchange(DateTime.Now, int.Parse(isaControlNumber), true);
                interchange.AuthorInfoQualifier            = ConfigurationManager.AppSettings["AuthorInfoQualifier"];
                interchange.AuthorInfo                     = ConfigurationManager.AppSettings["AuthorInfo"];
                interchange.SecurityInfoQualifier          = ConfigurationManager.AppSettings["SecurityInfoQualifier"];
                interchange.SecurityInfo                   = ConfigurationManager.AppSettings["SecurityInfo"];
                interchange.InterchangeSenderIdQualifier   = ConfigurationManager.AppSettings["InterchangeSenderIdQualifier"];
                interchange.InterchangeSenderId            = ConfigurationManager.AppSettings["InterchangeSenderId"];
                interchange.InterchangeReceiverIdQualifier = responses.First().SenderIdQualifier;
                interchange.InterchangeReceiverId          = responses.First().SenderId;
                interchange.SetElement(12, "00501");


                var group = interchange.AddFunctionGroup("FA", DateTime.Now, int.Parse(gsControlNumber));
                group.ApplicationSendersCode = ConfigurationManager.AppSettings["InterchangeSenderId"];
                group.VersionIdentifierCode  = "005010X231A1";

                group.Add999Transaction(responses);

                // This is a demonstration example only, change true to false to create continous x12 without line feeds.
                File.WriteAllText(outputFilename, interchange.SerializeToX12(true));
            }
        }
Example #2
0
        static void Main(string[] args)
        {
            var opts = new ExecutionOptions();

            try
            {
                opts.LoadOptions(args);
            }
            catch (ArgumentException exc)
            {
                Console.Write(exc.Message);
                return;
            }

            X12Parser parser = new X12Parser();

            foreach (var filename in Directory.GetFiles(opts.InputDirectory, opts.FilenamePattern))
            {
                FileInfo           inputFile = new FileInfo(filename);
                List <Interchange> list      = new List <Interchange>();
                using (FileStream fs = new FileStream(inputFile.FullName, FileMode.Open, FileAccess.Read))
                {
                    X12StreamReader    reader      = new X12StreamReader(fs, Encoding.UTF8);
                    X12FlatTransaction transaction = reader.ReadNextTransaction();
                    while (!string.IsNullOrEmpty(transaction.Transactions.First()))
                    {
                        string x12         = transaction.ToString();
                        var    interchange = parser.ParseMultiple(x12).First();
                        if (opts.LoopId == "ST")
                        {
                            list.Add(interchange);
                        }
                        else
                        {
                            list.AddRange(parser.UnbundleByLoop(interchange, opts.LoopId));
                        }
                        transaction = reader.ReadNextTransaction();
                    }
                }
                List <Interchange> interchanges = parser.ParseMultiple(new FileStream(filename, FileMode.Open, FileAccess.Read));
                for (int i = 0; i < list.Count; i++)
                {
                    string outputFilename = String.Format(opts.FormatString, opts.OutputDirectory, inputFile.Name, i + 1, inputFile.Extension);
                    using (FileStream outputFilestream = new FileStream(outputFilename, FileMode.Create, FileAccess.Write))
                    {
                        using (StreamWriter writer = new StreamWriter(outputFilestream))
                        {
                            writer.Write(list[i].SerializeToX12(opts.IncludeWhitespace));
                            writer.Close();
                        }
                        outputFilestream.Close();
                    }
                }
            }
        }
Example #3
0
        private Stream chunkParse(Stream input, Encoding encoding, int maxBatchSize)
        {
            OopFactory.X12.Parsing.X12Parser parser = new OopFactory.X12.Parsing.X12Parser(throwException);
            Stream       stream = new MemoryStream();
            StreamWriter writer = new StreamWriter(stream, encoding);

            writer.Write("<Interchanges>");
            // Break up output files by batch size
            X12StreamReader    reader = new X12StreamReader(stream, encoding);
            X12FlatTransaction currentTransactions = reader.ReadNextTransaction();
            X12FlatTransaction nextTransaction     = reader.ReadNextTransaction();
            int i = 1;

            while (!string.IsNullOrEmpty(nextTransaction.Transactions.First()))
            {
                if (currentTransactions.GetSize() + nextTransaction.GetSize() < maxBatchSize &&
                    currentTransactions.IsaSegment == nextTransaction.IsaSegment &&
                    currentTransactions.GsSegment == nextTransaction.GsSegment)
                {
                    currentTransactions.Transactions.AddRange(nextTransaction.Transactions);
                }
                else
                {
                    var interchange = parser.ParseMultiple(currentTransactions.ToString()).First().Serialize();
                    writer.Write(interchange.RemoveXmlDeclaration());
                    currentTransactions = nextTransaction;
                }
                nextTransaction = reader.ReadNextTransaction();
            }

            var finalInterchange = parser.ParseMultiple(currentTransactions.ToString()).First().Serialize();

            writer.Write(finalInterchange.RemoveXmlDeclaration());

            writer.Write("</Interchanges>");
            writer.Flush();

            stream.Position = 0;
            return(stream);
        }
Example #4
0
        /// <summary>
        /// Builds a collection of <see cref="FunctionalGroupResponse"/> objects from Transactions
        /// </summary>
        /// <param name="x12Stream">Stream containing X12 Transactions</param>
        /// <param name="encoding">Stream encoding for proper reading</param>
        /// <returns>Collection of <see cref="FunctionalGroupResponse"/> objects</returns>
        public virtual List <FunctionalGroupResponse> AcknowledgeTransactions(Stream x12Stream, Encoding encoding)
        {
            var responses = new Dictionary <string, FunctionalGroupResponse>();

            using (var reader = new X12StreamReader(x12Stream, encoding, this.ignoredChars))
            {
                X12FlatTransaction trans = reader.ReadNextTransaction();
                while (!string.IsNullOrEmpty(trans.Transactions.First()))
                {
                    string[] isaElements = reader.SplitSegment(trans.IsaSegment);
                    string[] gsElements  = reader.SplitSegment(trans.GsSegment);
                    string   functionalIdentifierCode = gsElements[1];
                    string   groupControlNumber       = gsElements[6];
                    string   versionIdentifierCode    = gsElements[8];

                    if (!responses.ContainsKey(groupControlNumber))
                    {
                        responses.Add(
                            groupControlNumber,
                            new FunctionalGroupResponse
                        {
                            SenderIdQualifier     = isaElements[5],
                            SenderId              = isaElements[6],
                            FunctionalIdCode      = functionalIdentifierCode,
                            GroupControlNumber    = groupControlNumber,
                            VersionIdentifierCode = versionIdentifierCode
                        });
                    }

                    TransactionSetResponse response = this.AcknowledgeTransaction(reader, functionalIdentifierCode, versionIdentifierCode, trans.Transactions[0]);
                    responses[groupControlNumber].TransactionSetResponses.Add(response);

                    trans = reader.ReadNextTransaction();
                }
            }

            return(responses.Values.ToList());
        }
        protected virtual TransactionSetResponse AcknowledgeTransaction(X12StreamReader reader, string functionalCode, string versionIdentifierCode, string transaction)
        {
            string[] stElements = reader.SplitSegment(transaction);
            var      response   = new TransactionSetResponse
            {
                TransactionSetIdentifierCode = stElements[1],
                TransactionSetControlNumber  = stElements[2]
            };

            if (stElements.Length >= 4)
            {
                response.ImplementationConventionReference = stElements[3];
            }

            var transactionSpec = _specFinder.FindTransactionSpec(functionalCode, versionIdentifierCode, response.TransactionSetIdentifierCode);

            if (transactionSpec == null)
            {
                response.SyntaxErrorCodes.Add("1"); // Transaction Set Not Supported
                response.AcknowledgmentCode = AcknowledgmentCodeEnum.R_Rejected;
                return(response);
            }

            #region Validate against transaction specification
            Stack <ContainerInformation> containers = new Stack <ContainerInformation>();
            var transactionContainer = new ContainerInformation {
                Spec = transactionSpec
            };
            containers.Push(transactionContainer);

            List <SegmentInformation> segmentInfos = new List <SegmentInformation>();
            string[] segments = transaction.Split(new char[] { reader.Delimiters.SegmentTerminator }, StringSplitOptions.RemoveEmptyEntries);
            for (int i = 0; i < segments.Length; i++)
            {
                string[] elements    = segments[i].Split(reader.Delimiters.ElementSeparator);
                var      segmentInfo = new SegmentInformation {
                    SegmentId = elements[0], SegmentPosition = i + 1, Elements = elements
                };
                segmentInfo.Spec = _specFinder.FindSegmentSpec(versionIdentifierCode, segmentInfo.SegmentId);
                segmentInfos.Add(segmentInfo);

                ContainerInformation currentContainer = containers.Peek();

                switch (segmentInfo.SegmentId)
                {
                case "ST":
                case "SE":
                    segmentInfo.LoopId = "";
                    transactionContainer.Segments.Add(segmentInfo);
                    break;

                case "HL":
                    string hlNumber       = segmentInfo.Elements[1];
                    string hlParentNumber = segmentInfo.Elements[2];
                    string hlLevelCode    = segmentInfo.Elements[3];
                    var    hlSpec         = transactionSpec.HierarchicalLoopSpecifications.FirstOrDefault(hls => hls.LevelCode == hlLevelCode);
                    if (hlSpec != null)
                    {
                        while (!(containers.Peek().Spec is TransactionSpecification))
                        {
                            if (containers.Peek().HLoopNumber == hlParentNumber)
                            {
                                break;
                            }
                            containers.Pop();
                        }
                        segmentInfo.LoopId = hlSpec.LoopId;
                        var hlContainer = new ContainerInformation {
                            Spec = hlSpec, HLoopNumber = hlNumber
                        };
                        hlContainer.Segments.Add(segmentInfo);
                        containers.Peek().Containers.Add(hlContainer);
                        containers.Push(hlContainer);
                    }
                    else
                    {
                        response.SegmentErrors.Add(CreateDataElementError(segmentInfo, 3, "I6", hlLevelCode)); //Code Value Not Used in Implementation
                        response.AcknowledgmentCode = AcknowledgmentCodeEnum.X_Rejected_ContentCouldNotBeAnalyzed;
                        return(response);                                                                      // end validation if HL cannot be recognized since hl spec will not be available
                    }
                    break;

                default:
                    bool matchFound = false;
                    do
                    {
                        var matchingLoopSpecs = currentContainer.Spec.LoopSpecifications.Where(ls => ls.StartingSegment.SegmentId == segmentInfo.SegmentId).ToList();

                        if (matchingLoopSpecs.Count > 0)
                        {
                            IContainerSpecification matchingLoopSpec = null;
                            if (matchingLoopSpecs.Count == 1)
                            {
                                matchingLoopSpec = matchingLoopSpecs.First();
                            }
                            else
                            {
                                string entityCode = elements[1];
                                matchingLoopSpec = matchingLoopSpecs.FirstOrDefault(ls => ls.StartingSegment.EntityIdentifiers.Exists(ei => ei.Code == entityCode));
                            }

                            if (matchingLoopSpec != null)
                            {
                                segmentInfo.LoopId = matchingLoopSpec.LoopId;
                                var loopContainer = new ContainerInformation {
                                    Spec = matchingLoopSpec
                                };
                                loopContainer.Segments.Add(segmentInfo);
                                containers.Peek().Containers.Add(loopContainer);
                                containers.Push(loopContainer);
                                matchFound = true;
                            }
                            else
                            {
                                response.SegmentErrors.Add(CreateSegmentError(segmentInfo, "6"));     //Segment Not in Defined Transaction Set
                                response.AcknowledgmentCode = AcknowledgmentCodeEnum.X_Rejected_ContentCouldNotBeAnalyzed;
                                return(response);
                            }
                        }
                        else if (currentContainer.Spec.SegmentSpecifications.Exists(ss => ss.SegmentId == segmentInfo.SegmentId))
                        {
                            segmentInfo.LoopId = currentContainer.Spec.LoopId;
                            currentContainer.Segments.Add(segmentInfo);
                            matchFound = true;
                        }
                        else
                        {
                            if (currentContainer.Spec is TransactionSpecification)
                            {
                                response.SegmentErrors.Add(CreateSegmentError(segmentInfo, "2")); // Unexpected segment
                                response.AcknowledgmentCode = AcknowledgmentCodeEnum.X_Rejected_ContentCouldNotBeAnalyzed;
                                return(response);                                                 // end validation if unrecognized segment encountered (cannot guarantee we are pointing at correct container)
                            }
                            else
                            {
                                containers.Pop();
                                currentContainer = containers.Peek();
                            }
                        }
                    } while (!matchFound);
                    break;
                }
                response.SegmentErrors.AddRange(ValidateSegmentAgainstSpec(segmentInfo));
            }

            response.SegmentErrors.AddRange(ValidateContainerAgainstSpec(transactionContainer));

            #endregion

            #region Validate transaction trailer
            var trailerSegment = segmentInfos.FirstOrDefault(si => si.SegmentId == "SE");
            if (trailerSegment == null)
            {
                response.SyntaxErrorCodes.Add("2"); //Transaction Set Trailer Missing
            }
            else
            {
                if (trailerSegment.Elements.Length <= 2 || trailerSegment.Elements[2] != response.TransactionSetControlNumber)
                {
                    response.SyntaxErrorCodes.Add("3"); // Transaction Set Control Number in Header and Trailer Do Not Match
                }
                if (trailerSegment.Elements.Length >= 2)
                {
                    int segmentCount;
                    int.TryParse(trailerSegment.Elements[1], out segmentCount);
                    if (segmentCount != segmentInfos.Count)
                    {
                        response.SyntaxErrorCodes.Add("4"); // Number of Included Segments Does Not Match Actual Count
                    }
                }
                else
                {
                    response.SyntaxErrorCodes.Add("4"); // Number of Included Segments Does Not Match Actual Count
                }
            }

            #endregion

            if (response.SegmentErrors.Count > 0 || response.SyntaxErrorCodes.Count > 0)
            {
                if (response.SegmentErrors.Count > 0)
                {
                    response.SyntaxErrorCodes.Add("5"); //One or More Segments in Error
                }
                if (response.AcknowledgmentCode == AcknowledgmentCodeEnum.A_Accepted)
                {
                    response.AcknowledgmentCode = AcknowledgmentCodeEnum.E_Accepted_ButErrorsWereNoted;
                }
            }
            return(response);
        }
Example #6
0
        /// <summary>
        /// Main entry point for the application
        /// </summary>
        /// <param name="args">Additional command line arguments to parse</param>
        public static void Main(string[] args)
        {
            int maxBatchSize = 10 * 1024 * 1024;

            if (ConfigurationManager.AppSettings["MaxBatchSize"] != null)
            {
                maxBatchSize = Convert.ToInt32(ConfigurationManager.AppSettings["MaxBatchSize"]);
            }

            bool throwException = Convert.ToBoolean(ConfigurationManager.AppSettings["ThrowExceptionOnSyntaxErrors"]);

            string x12Filename = args[0];

            if (!File.Exists(x12Filename))
            {
                Console.WriteLine(Resources.FileNotFoundError, DateTime.Now.ToLongTimeString(), x12Filename);
                return;
            }

            string outputFilename = args.Length > 1 ? args[1] : x12Filename + ".xml";

            var parser = new X12Parser(throwException);

            parser.ParserWarning += HandleParserWarning;

            Console.WriteLine(Resources.ParserInitializingMessage);
            Console.WriteLine(Resources.ConfigurationUnderlineString);
            Console.WriteLine($"Max Batch Size: {maxBatchSize}");
            Console.WriteLine($"Throw Exception on Syntax Error: {throwException}");
            Console.WriteLine($"Input Filename: '{x12Filename}'");
            Console.WriteLine($"Output Filename: '{outputFilename}'");
            Console.WriteLine();
            Console.WriteLine(Resources.ConfigurationUnderlineString);

            var header = new byte[6];

            using (var fs = new FileStream(x12Filename, FileMode.Open, FileAccess.Read))
            {
                // peak at first 6 characters to determine if this is a unicode file
                fs.Read(header, 0, 6);
                fs.Close();
            }

            Encoding encoding = (header[1] == 0 && header[3] == 0 && header[5] == 0) ? Encoding.Unicode : Encoding.UTF8;

            if (new FileInfo(x12Filename).Length <= maxBatchSize)
            {
                using (var fs = new FileStream(x12Filename, FileMode.Open, FileAccess.Read))
                {
                    IList <Interchange> interchanges;
                    Console.WriteLine(Resources.ParserParsingFileMessage);

                    try
                    {
                        interchanges = parser.ParseMultiple(fs, encoding);
                    }
                    catch (Exception exception)
                    {
                        Console.WriteLine(Resources.ParsingError, DateTime.Now.ToLongTimeString(), exception.Message);
                        return;
                    }

                    if (interchanges.Count >= 1)
                    {
                        using (var outputFs = new FileStream(outputFilename, FileMode.Create))
                        {
                            Console.WriteLine(Resources.ParserSerializingFileMessage);

                            try
                            {
                                interchanges.First().Serialize(outputFs);
                            }
                            catch (Exception exception)
                            {
                                Console.WriteLine(Resources.SerializationError, DateTime.Now.ToLongTimeString(), exception.Message);
                                return;
                            }
                        }
                    }

                    if (interchanges.Count > 1)
                    {
                        for (int i = 1; i < interchanges.Count; i++)
                        {
                            outputFilename = $"{(args.Length > 1 ? args[1] : x12Filename)}_{i + 1}.xml";
                            using (var outputFs = new FileStream(outputFilename, FileMode.Create))
                            {
                                Console.WriteLine(Resources.ParserSerializingFileMessage);

                                try
                                {
                                    interchanges[i].Serialize(outputFs);
                                }
                                catch (Exception exception)
                                {
                                    Console.WriteLine(Resources.SerializationError, DateTime.Now.ToLongTimeString(), exception.Message);
                                    return;
                                }
                            }
                        }
                    }
                }
            }
            else
            {
                using (var fs = new FileStream(x12Filename, FileMode.Open, FileAccess.Read))
                {
                    // Break up output files by batch size
                    var reader = new X12StreamReader(fs, encoding);
                    Console.WriteLine(Resources.ParserReadingTransactionsMessage);

                    X12FlatTransaction currentTransactions = reader.ReadNextTransaction();
                    X12FlatTransaction nextTransaction     = reader.ReadNextTransaction();
                    int i = 1;

                    while (!string.IsNullOrEmpty(nextTransaction.Transactions.First()))
                    {
                        if (currentTransactions.GetSize() + nextTransaction.GetSize() < maxBatchSize &&
                            currentTransactions.IsaSegment == nextTransaction.IsaSegment &&
                            currentTransactions.GsSegment == nextTransaction.GsSegment)
                        {
                            currentTransactions.Transactions.AddRange(nextTransaction.Transactions);
                        }
                        else
                        {
                            outputFilename = $"{(args.Length > 1 ? args[1] : x12Filename)}_{i++}.xml";
                            using (var outputFs = new FileStream(outputFilename, FileMode.Create))
                            {
                                Console.WriteLine(Resources.ParserParsingSerialzingTransactionMessage);

                                try
                                {
                                    parser.ParseMultiple(currentTransactions.ToString()).First().Serialize(outputFs);
                                }
                                catch (Exception exception)
                                {
                                    Console.WriteLine(Resources.ParsingError, DateTime.Now.ToLongTimeString(), exception.Message);
                                    return;
                                }
                            }

                            currentTransactions = nextTransaction;
                        }

                        nextTransaction = reader.ReadNextTransaction();
                    }

                    outputFilename = $"{(args.Length > 1 ? args[1] : x12Filename)}_{i++}.xml";
                    using (var outputFs = new FileStream(outputFilename, FileMode.Create))
                    {
                        Console.WriteLine(Resources.ParserParsingSerialzingTransactionMessage);

                        try
                        {
                            parser.ParseMultiple(currentTransactions.ToString()).First().Serialize(outputFs);
                        }
                        catch (Exception exception)
                        {
                            Console.WriteLine(Resources.ParsingError, DateTime.Now.ToLongTimeString(), exception.Message);
                            return;
                        }
                    }
                }
            }

            Console.WriteLine(Resources.ParserCompleteMessage);
        }
Example #7
0
        static void Main(string[] args)
        {
            int maxBatchSize = 10 * 1012 * 1012; // 10 Mbytes

            if (ConfigurationManager.AppSettings["MaxBatchSize"] != null)
            {
                maxBatchSize = Convert.ToInt32(ConfigurationManager.AppSettings["MaxBatchSize"]);
            }

            bool throwException = Convert.ToBoolean(ConfigurationManager.AppSettings["ThrowExceptionOnSyntaxErrors"]);

            string x12Filename    = args[0];
            string outputFilename = args.Length > 1 ? args[1] : x12Filename + ".xml";

            OopFactory.X12.Parsing.X12Parser parser = new Parsing.X12Parser(throwException);
            parser.ParserWarning += new Parsing.X12Parser.X12ParserWarningEventHandler(parser_ParserWarning);

            byte[] header = new byte[6];
            using (FileStream fs = new FileStream(x12Filename, FileMode.Open, FileAccess.Read))
            {
                // peak at first 6 characters to determine if this is a unicode file
                fs.Read(header, 0, 6);
                fs.Close();
            }
            Encoding encoding = (header[1] == 0 && header[3] == 0 && header[5] == 0) ? Encoding.Unicode : Encoding.UTF8;

            if (new FileInfo(x12Filename).Length <= maxBatchSize)
            {
                using (FileStream fs = new FileStream(x12Filename, FileMode.Open, FileAccess.Read))
                {
                    var interchanges = parser.ParseMultiple(fs, encoding);
                    if (interchanges.Count >= 1)
                    {
                        using (FileStream outputFs = new FileStream(outputFilename, FileMode.Create))
                        {
                            interchanges.First().Serialize(outputFs);
                        }
                    }
                    if (interchanges.Count > 1)
                    {
                        for (int i = 1; i < interchanges.Count; i++)
                        {
                            outputFilename = string.Format("{0}_{1}.xml", args.Length > 1 ? args[1] : x12Filename, i + 1);
                            using (FileStream outputFs = new FileStream(outputFilename, FileMode.Create))
                            {
                                interchanges[i].Serialize(outputFs);
                            }
                        }
                    }
                }
            }
            else
            {
                using (FileStream fs = new FileStream(x12Filename, FileMode.Open, FileAccess.Read))
                {
                    // Break up output files by batch size
                    X12StreamReader    reader = new X12StreamReader(fs, encoding);
                    X12FlatTransaction currentTransactions = reader.ReadNextTransaction();
                    X12FlatTransaction nextTransaction     = reader.ReadNextTransaction();
                    int i = 1;
                    while (!string.IsNullOrEmpty(nextTransaction.Transactions.First()))
                    {
                        if (currentTransactions.GetSize() + nextTransaction.GetSize() < maxBatchSize &&
                            currentTransactions.IsaSegment == nextTransaction.IsaSegment &&
                            currentTransactions.GsSegment == nextTransaction.GsSegment)
                        {
                            currentTransactions.Transactions.AddRange(nextTransaction.Transactions);
                        }
                        else
                        {
                            outputFilename = string.Format("{0}_{1}.xml", args.Length > 1 ? args[1] : x12Filename, i++);
                            using (FileStream outputFs = new FileStream(outputFilename, FileMode.Create))
                            {
                                parser.ParseMultiple(currentTransactions.ToString()).First().Serialize(outputFs);
                            }
                            currentTransactions = nextTransaction;
                        }

                        nextTransaction = reader.ReadNextTransaction();
                    }

                    outputFilename = string.Format("{0}_{1}.xml", args.Length > 1 ? args[1] : x12Filename, i++);
                    using (FileStream outputFs = new FileStream(outputFilename, FileMode.Create))
                    {
                        parser.ParseMultiple(currentTransactions.ToString()).First().Serialize(outputFs);
                    }
                }
            }
        }
Example #8
0
        /// <summary>
        /// Builds a <see cref="TransactionSetResponse"/> object from the provided stream
        /// </summary>
        /// <param name="reader">Stream to pull transaction set data from</param>
        /// <param name="functionalCode">Function group code to associate with transaction set</param>
        /// <param name="versionIdentifierCode">Specification version code</param>
        /// <param name="transaction">Transaction segment string to be parsed</param>
        /// <returns>Transaction set response whether the set is valid, and the segment data</returns>
        protected virtual TransactionSetResponse AcknowledgeTransaction(X12StreamReader reader, string functionalCode, string versionIdentifierCode, string transaction)
        {
            string[] transactionElements = reader.SplitSegment(transaction);
            var      response            = new TransactionSetResponse
            {
                TransactionSetIdentifierCode = transactionElements[1],
                TransactionSetControlNumber  = transactionElements[2]
            };

            if (transactionElements.Length >= 4)
            {
                response.ImplementationConventionReference = transactionElements[3];
            }

            TransactionSpecification transactionSpec = this.specFinder.FindTransactionSpec(
                functionalCode,
                versionIdentifierCode,
                response.TransactionSetIdentifierCode);

            if (transactionSpec == null)
            {
                response.SyntaxErrorCodes.Add("1");
                response.AcknowledgmentCode = AcknowledgmentCode.R_Rejected;
                return(response);
            }

            var containers           = new Stack <ContainerInformation>();
            var transactionContainer = new ContainerInformation {
                Spec = transactionSpec
            };

            containers.Push(transactionContainer);
            var segmentInfos = new List <SegmentInformation>();

            string[] segments = transaction.Split(new[] { reader.Delimiters.SegmentTerminator }, System.StringSplitOptions.RemoveEmptyEntries);
            for (int i = 0; i < segments.Length; i++)
            {
                string[] elements    = segments[i].Split(reader.Delimiters.ElementSeparator);
                var      segmentInfo = new SegmentInformation {
                    SegmentId = elements[0], SegmentPosition = i + 1, Elements = elements
                };
                segmentInfo.Spec = this.specFinder.FindSegmentSpec(versionIdentifierCode, segmentInfo.SegmentId);
                segmentInfos.Add(segmentInfo);

                ContainerInformation currentContainer = containers.Peek();

                switch (segmentInfo.SegmentId)
                {
                case "ST":
                case "SE":
                    segmentInfo.LoopId = string.Empty;
                    transactionContainer.Segments.Add(segmentInfo);
                    break;

                case "HL":
                    string hloopNumber       = segmentInfo.Elements[1];
                    string hloopParentNumber = segmentInfo.Elements[2];
                    string hloopLevelCode    = segmentInfo.Elements[3];
                    HierarchicalLoopSpecification hloopSpec = transactionSpec.HierarchicalLoopSpecifications.FirstOrDefault(hls => hls.LevelCode == hloopLevelCode);
                    if (hloopSpec != null)
                    {
                        while (!(containers.Peek().Spec is TransactionSpecification))
                        {
                            if (containers.Peek().HLoopNumber == hloopParentNumber)
                            {
                                break;
                            }

                            containers.Pop();
                        }

                        segmentInfo.LoopId = hloopSpec.LoopId;
                        var hloopContainer = new ContainerInformation {
                            Spec = hloopSpec, HLoopNumber = hloopNumber
                        };
                        hloopContainer.Segments.Add(segmentInfo);
                        containers.Peek().Containers.Add(hloopContainer);
                        containers.Push(hloopContainer);
                    }
                    else
                    {
                        response.SegmentErrors.Add(this.CreateDataElementError(segmentInfo, 3, "I6", hloopLevelCode));
                        response.AcknowledgmentCode = AcknowledgmentCode.X_Rejected_ContentCouldNotBeAnalyzed;
                    }

                    break;

                default:
                    bool matchFound = false;
                    do
                    {
                        var matchingLoopSpecs = currentContainer.Spec.LoopSpecifications.Where(ls => ls.StartingSegment.SegmentId == segmentInfo.SegmentId).ToList();

                        if (matchingLoopSpecs.Count > 0)
                        {
                            IContainerSpecification matchingLoopSpec;
                            if (matchingLoopSpecs.Count == 1)
                            {
                                matchingLoopSpec = matchingLoopSpecs.First();
                            }
                            else
                            {
                                string entityCode = elements[1];
                                matchingLoopSpec = matchingLoopSpecs.FirstOrDefault(ls => ls.StartingSegment.EntityIdentifiers.Exists(ei => ei.Code == entityCode));
                            }

                            if (matchingLoopSpec != null)
                            {
                                segmentInfo.LoopId = matchingLoopSpec.LoopId;
                                var loopContainer = new ContainerInformation {
                                    Spec = matchingLoopSpec
                                };
                                loopContainer.Segments.Add(segmentInfo);
                                containers.Peek().Containers.Add(loopContainer);
                                containers.Push(loopContainer);
                                matchFound = true;
                            }
                            else
                            {
                                response.SegmentErrors.Add(this.CreateSegmentError(segmentInfo, "6"));
                                response.AcknowledgmentCode = AcknowledgmentCode.X_Rejected_ContentCouldNotBeAnalyzed;
                                return(response);
                            }
                        }
                        else if (currentContainer.Spec.SegmentSpecifications.Exists(ss => ss.SegmentId == segmentInfo.SegmentId))
                        {
                            segmentInfo.LoopId = currentContainer.Spec.LoopId;
                            currentContainer.Segments.Add(segmentInfo);
                            matchFound = true;
                        }
                        else
                        {
                            if (currentContainer.Spec is TransactionSpecification)
                            {
                                response.SegmentErrors.Add(this.CreateSegmentError(segmentInfo, "2"));
                                response.AcknowledgmentCode = AcknowledgmentCode.X_Rejected_ContentCouldNotBeAnalyzed;
                                return(response);
                            }

                            containers.Pop();
                            currentContainer = containers.Peek();
                        }
                    }while (!matchFound);

                    break;
                }

                response.SegmentErrors.AddRange(this.ValidateSegmentAgainstSpec(segmentInfo));
            }

            response.SegmentErrors.AddRange(this.ValidateContainerAgainstSpec(transactionContainer));

            var trailerSegment = segmentInfos.FirstOrDefault(si => si.SegmentId == "SE");

            if (trailerSegment == null)
            {
                response.SyntaxErrorCodes.Add("2");
            }
            else
            {
                if (trailerSegment.Elements.Length <= 2 || trailerSegment.Elements[2] != response.TransactionSetControlNumber)
                {
                    response.SyntaxErrorCodes.Add("3");
                }

                if (trailerSegment.Elements.Length >= 2)
                {
                    int segmentCount;
                    int.TryParse(trailerSegment.Elements[1], out segmentCount);
                    if (segmentCount != segmentInfos.Count)
                    {
                        response.SyntaxErrorCodes.Add("4");
                    }
                }
                else
                {
                    response.SyntaxErrorCodes.Add("4");
                }
            }

            if (response.SegmentErrors.Count > 0 || response.SyntaxErrorCodes.Count > 0)
            {
                if (response.SegmentErrors.Count > 0)
                {
                    response.SyntaxErrorCodes.Add("5");
                }

                if (response.AcknowledgmentCode == AcknowledgmentCode.A_Accepted)
                {
                    response.AcknowledgmentCode = AcknowledgmentCode.E_Accepted_ButErrorsWereNoted;
                }
            }

            return(response);
        }