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)); } }
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(); } } } }
public List <Interchange> ParseMultiple(Stream stream, Encoding encoding) { var envelopes = new List <Interchange>(); using (X12StreamReader reader = new X12StreamReader(stream, encoding)) { Interchange envelop = new Interchange(_specFinder, reader.CurrentIsaSegment); envelopes.Add(envelop); Container currentContainer = envelop; FunctionGroup fg = null; Transaction tr = null; Dictionary <string, HierarchicalLoop> hloops = new Dictionary <string, HierarchicalLoop>(); string segmentString = reader.ReadNextSegment(); string segmentId = reader.ReadSegmentId(segmentString); int segmentIndex = 1; while (segmentString.Length > 0) { switch (segmentId) { case "ISA": envelop = new Interchange(_specFinder, segmentString + reader.Delimiters.SegmentTerminator); envelopes.Add(envelop); currentContainer = envelop; fg = null; tr = null; hloops = new Dictionary <string, HierarchicalLoop>(); break; case "IEA": if (envelop == null) { throw new InvalidOperationException(string.Format("Segment {0} does not have a matching ISA segment preceding it.", segmentString)); } envelop.SetTerminatingTrailerSegment(segmentString); break; case "GS": if (envelop == null) { throw new InvalidOperationException(String.Format("Segment '{0}' cannot occur before and ISA segment.", segmentString)); } currentContainer = fg = envelop.AddFunctionGroup(segmentString);; break; case "GE": if (fg == null) { throw new InvalidOperationException(String.Format("Segment '{0}' does not have a matching GS segment precending it.", segmentString)); } fg.SetTerminatingTrailerSegment(segmentString); fg = null; break; case "ST": if (fg == null) { throw new InvalidOperationException(string.Format("segment '{0}' cannot occur without a preceding GS segment.", segmentString)); } segmentIndex = 1; currentContainer = tr = fg.AddTransaction(segmentString); hloops = new Dictionary <string, HierarchicalLoop>(); break; case "SE": if (tr == null) { throw new InvalidOperationException(string.Format("Segment '{0}' does not have a matching ST segment preceding it.", segmentString)); } tr.SetTerminatingTrailerSegment(segmentString); tr = null; break; case "HL": Segment hlSegment = new Segment(null, reader.Delimiters, segmentString); string id = hlSegment.GetElement(1); string parentId = hlSegment.GetElement(2); if (parentId == "") { currentContainer = tr.AddHLoop(segmentString); } else { if (hloops.ContainsKey(parentId)) { currentContainer = hloops[parentId].AddHLoop(segmentString); } else { throw new InvalidOperationException(String.Format("Hierarchical Loop {0} expects Parent ID {1} which did not occur preceding it.", id, parentId)); } } if (hloops.ContainsKey(id)) { throw new InvalidOperationException(String.Format("Hierarchical Loop {0} cannot be added to transaction {1} because the ID {2} already exists.", segmentString, tr.ControlNumber, id)); } hloops.Add(id, (HierarchicalLoop)currentContainer); break; case "TA1": // Technical acknowledgement if (envelop == null) { throw new InvalidOperationException(string.Format("Segment {0} does not have a matching ISA segment preceding it.", segmentString)); } envelop.AddSegment(segmentString); break; default: while (currentContainer != null) { if (currentContainer.AddSegment(segmentString) != null) { break; } else { if (currentContainer is LoopContainer) { LoopContainer loopContainer = (LoopContainer)currentContainer; Loop newLoop = loopContainer.AddLoop(segmentString); if (newLoop != null) { currentContainer = newLoop; break; } else { if (currentContainer is Transaction) { var tran = (Transaction)currentContainer; throw new TransactionValidationException( "Segment '{3}' in segment position {4} within transaction '{1}' cannot be identified within the supplied specification for transaction set {0}.", tran.IdentifierCode, tran.ControlNumber, "", segmentString, segmentIndex); } else { currentContainer = currentContainer.Parent; continue; } } } else { break; } } } break; } segmentString = reader.ReadNextSegment(); segmentId = reader.ReadSegmentId(segmentString); segmentIndex++; } return(envelopes); } }
static void Main(string[] args) { int maxBatchSize = 10 * 1012 * 1012; // 10 Mbytes if (ConfigurationManager.AppSettings["MaxBatchSize"] != null) maxBatchSize = Convert.ToInt32(ConfigurationManager.AppSettings["MaxBatchSize"]); string x12Filename = args[0]; string outputFilename = args.Length > 1 ? args[1] : x12Filename + ".xml"; OopFactory.X12.Parsing.X12Parser parser = new Parsing.X12Parser(); 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); } } } }
public List<Interchange> ParseMultiple(Stream stream, Encoding encoding) { var envelopes = new List<Interchange>(); using (X12StreamReader reader = new X12StreamReader(stream, encoding)) { Interchange envelop = new Interchange(_specFinder, reader.CurrentIsaSegment); envelopes.Add(envelop); Container currentContainer = envelop; FunctionGroup fg = null; Transaction tr = null; Dictionary<string, HierarchicalLoop> hloops = new Dictionary<string, HierarchicalLoop>(); string segmentString = reader.ReadNextSegment(); string segmentId = reader.ReadSegmentId(segmentString); int segmentIndex = 1; while (segmentString.Length > 0) { switch (segmentId) { case "ISA": envelop = new Interchange(_specFinder, segmentString + reader.Delimiters.SegmentTerminator); envelopes.Add(envelop); currentContainer = envelop; fg = null; tr = null; hloops = new Dictionary<string, HierarchicalLoop>(); break; case "IEA": if (envelop == null) throw new InvalidOperationException(string.Format("Segment {0} does not have a matching ISA segment preceding it.", segmentString)); envelop.SetTerminatingTrailerSegment(segmentString); break; case "GS": if (envelop == null) throw new InvalidOperationException(String.Format("Segment '{0}' cannot occur before and ISA segment.", segmentString)); currentContainer = fg = envelop.AddFunctionGroup(segmentString); ; break; case "GE": if (fg == null) throw new InvalidOperationException(String.Format("Segment '{0}' does not have a matching GS segment precending it.", segmentString)); fg.SetTerminatingTrailerSegment(segmentString); fg = null; break; case "ST": if (fg == null) throw new InvalidOperationException(string.Format("segment '{0}' cannot occur without a preceding GS segment.", segmentString)); segmentIndex = 1; currentContainer = tr = fg.AddTransaction(segmentString); hloops = new Dictionary<string, HierarchicalLoop>(); break; case "SE": if (tr == null) throw new InvalidOperationException(string.Format("Segment '{0}' does not have a matching ST segment preceding it.", segmentString)); tr.SetTerminatingTrailerSegment(segmentString); tr = null; break; case "HL": Segment hlSegment = new Segment(null, reader.Delimiters, segmentString); string id = hlSegment.GetElement(1); string parentId = hlSegment.GetElement(2); if (parentId == "") currentContainer = tr.AddHLoop(segmentString); else { if (hloops.ContainsKey(parentId)) currentContainer = hloops[parentId].AddHLoop(segmentString); else throw new InvalidOperationException(String.Format("Hierarchical Loop {0} expects Parent ID {1} which did not occur preceding it.", id, parentId)); } if (hloops.ContainsKey(id)) throw new InvalidOperationException(String.Format("Hierarchical Loop {0} cannot be added to transaction {1} because the ID {2} already exists.", segmentString, tr.ControlNumber, id)); hloops.Add(id, (HierarchicalLoop)currentContainer); break; case "TA1": // Technical acknowledgement if (envelop == null) throw new InvalidOperationException(string.Format("Segment {0} does not have a matching ISA segment preceding it.", segmentString)); envelop.AddSegment(segmentString); break; default: while (currentContainer != null) { if (currentContainer.AddSegment(segmentString) != null) break; else { if (currentContainer is LoopContainer) { LoopContainer loopContainer = (LoopContainer)currentContainer; Loop newLoop = loopContainer.AddLoop(segmentString); if (newLoop != null) { currentContainer = newLoop; break; } else { if (currentContainer is Transaction) { var tran = (Transaction)currentContainer; throw new TransactionValidationException( "Segment '{3}' in segment position {4} within transaction '{1}' cannot be identified within the supplied specification for transaction set {0}.", tran.IdentifierCode, tran.ControlNumber, "", segmentString, segmentIndex); } else { currentContainer = currentContainer.Parent; continue; } } } else break; } } break; } segmentString = reader.ReadNextSegment(); segmentId = reader.ReadSegmentId(segmentString); segmentIndex++; } return envelopes; } }
public List <Interchange> ParseMultiple(Stream stream, Encoding encoding) { var envelopes = new List <Interchange>(); using (X12StreamReader reader = new X12StreamReader(stream, encoding, _ignoredChars)) { Interchange envelop = new Interchange(_specFinder, reader.CurrentIsaSegment); envelopes.Add(envelop); Container currentContainer = envelop; FunctionGroup fg = null; Transaction tr = null; Dictionary <string, HierarchicalLoop> hloops = new Dictionary <string, HierarchicalLoop>(); string segmentString = reader.ReadNextSegment(); string segmentId = reader.ReadSegmentId(segmentString); int segmentIndex = 1; Stack <string> containerStack = new Stack <string>(); while (segmentString.Length > 0) { switch (segmentId) { case "ISA": envelop = new Interchange(_specFinder, segmentString + reader.Delimiters.SegmentTerminator); envelopes.Add(envelop); currentContainer = envelop; fg = null; tr = null; hloops = new Dictionary <string, HierarchicalLoop>(); break; case "IEA": if (envelop == null) { throw new InvalidOperationException(string.Format("Segment {0} does not have a matching ISA segment preceding it.", segmentString)); } envelop.SetTerminatingTrailerSegment(segmentString); break; case "GS": if (envelop == null) { throw new InvalidOperationException(String.Format("Segment '{0}' cannot occur before and ISA segment.", segmentString)); } currentContainer = fg = envelop.AddFunctionGroup(segmentString);; break; case "GE": if (fg == null) { throw new InvalidOperationException(String.Format("Segment '{0}' does not have a matching GS segment precending it.", segmentString)); } fg.SetTerminatingTrailerSegment(segmentString); fg = null; break; case "ST": if (fg == null) { throw new InvalidOperationException(string.Format("segment '{0}' cannot occur without a preceding GS segment.", segmentString)); } segmentIndex = 1; currentContainer = tr = fg.AddTransaction(segmentString); hloops = new Dictionary <string, HierarchicalLoop>(); break; case "SE": if (tr == null) { throw new InvalidOperationException(string.Format("Segment '{0}' does not have a matching ST segment preceding it.", segmentString)); } tr.SetTerminatingTrailerSegment(segmentString); tr = null; break; case "HL": Segment hlSegment = new Segment(null, reader.Delimiters, segmentString); string id = hlSegment.GetElement(1); string parentId = hlSegment.GetElement(2); string levelCode = hlSegment.GetElement(3); while (!(currentContainer is HierarchicalLoopContainer) || !((HierarchicalLoopContainer)currentContainer).AllowsHierarchicalLoop(levelCode)) { if (currentContainer.Parent != null) { currentContainer = currentContainer.Parent; } else { throw new InvalidOperationException(String.Format("Heierchical Loop {0} cannot be added to transaction set {1} because it's specification cannot be identified.", segmentString, tr.ControlNumber)); } } bool parentFound = false; if (parentId != "") { if (hloops.ContainsKey(parentId)) { parentFound = true; currentContainer = hloops[parentId].AddHLoop(segmentString); } else { if (_throwExceptionOnSyntaxErrors) { throw new InvalidOperationException(String.Format("Hierarchical Loop {0} expects Parent ID {1} which did not occur preceding it. To change this to a warning, pass throwExceptionOnSyntaxErrors = false to the X12Parser constructor.", id, parentId)); } else { OnParserWarning(new X12ParserWarningEventArgs { FileIsValid = false, InterchangeControlNumber = envelop.InterchangeControlNumber, FunctionalGroupControlNumber = fg.ControlNumber, TransactionControlNumber = tr.ControlNumber, SegmentPositionInInterchange = segmentIndex, Segment = segmentString, SegmentId = segmentId, Message = String.Format("Hierarchical Loop {0} expects Parent ID {1} which did not occur preceding it. This will be parsed as if it has no parent, but the file may not be valid.", id, parentId) }); } } } if (parentId == "" || !parentFound) { while (!(currentContainer is HierarchicalLoopContainer && ((HierarchicalLoopContainer)currentContainer).HasHierachicalSpecs())) { currentContainer = currentContainer.Parent; } currentContainer = ((HierarchicalLoopContainer)currentContainer).AddHLoop(segmentString); //hloops = new Dictionary<string, HierarchicalLoop>(); } if (hloops.ContainsKey(id)) { throw new InvalidOperationException(String.Format("Hierarchical Loop {0} cannot be added to transaction {1} because the ID {2} already exists.", segmentString, tr.ControlNumber, id)); } hloops.Add(id, (HierarchicalLoop)currentContainer); break; case "TA1": // Technical acknowledgement if (envelop == null) { throw new InvalidOperationException(string.Format("Segment {0} does not have a matching ISA segment preceding it.", segmentString)); } envelop.AddSegment(segmentString); break; default: var originalContainer = currentContainer; containerStack.Clear(); while (currentContainer != null) { if (currentContainer.AddSegment(segmentString) != null) { if (segmentId == "LE") { currentContainer = currentContainer.Parent; } break; } else { if (currentContainer is LoopContainer) { LoopContainer loopContainer = (LoopContainer)currentContainer; Loop newLoop = loopContainer.AddLoop(segmentString); if (newLoop != null) { currentContainer = newLoop; break; } else { if (currentContainer is Transaction) { var tran = (Transaction)currentContainer; if (_throwExceptionOnSyntaxErrors) { throw new TransactionValidationException( "Segment '{3}' in segment position {4} within transaction '{1}' cannot be identified within the supplied specification for transaction set {0} in any of the expected loops: {5}. To change this to a warning, pass throwExceptionOnSyntaxErrors = false to the X12Parser constructor.", tran.IdentifierCode, tran.ControlNumber, "", segmentString, segmentIndex, string.Join(",", containerStack)); } else { currentContainer = originalContainer; currentContainer.AddSegment(segmentString, true); OnParserWarning(new X12ParserWarningEventArgs { FileIsValid = false, InterchangeControlNumber = envelop.InterchangeControlNumber, FunctionalGroupControlNumber = fg.ControlNumber, TransactionControlNumber = tran.ControlNumber, SegmentPositionInInterchange = segmentIndex, SegmentId = segmentId, Segment = segmentString, Message = string.Format("Segment '{3}' in segment position {4} within transaction '{1}' cannot be identified within the supplied specification for transaction set {0} in any of the expected loops: {5}. It will be added to loop {6}, but this may invalidate all subsequent segments.", tran.IdentifierCode, tran.ControlNumber, "", segmentString, segmentIndex, string.Join(",", containerStack), containerStack.LastOrDefault()) }); break; } } else { if (currentContainer is Loop) { containerStack.Push(((Loop)currentContainer).Specification.LoopId); } if (currentContainer is HierarchicalLoop) { var hloop = ((HierarchicalLoop)currentContainer); containerStack.Push(string.Format("{0}[{1}]", hloop.Specification.LoopId, hloop.Id)); } currentContainer = currentContainer.Parent; continue; } } } else { break; } } } break; } segmentString = reader.ReadNextSegment(); segmentId = reader.ReadSegmentId(segmentString); segmentIndex++; } return(envelopes); } }