/// <summary> /// Find corrosponding Pluglet for given segmentname and create new segment /// </summary> /// <param name="segmentName"></param> /// <param name="segmentDetails"></param> private void CreateAndAddNewSegment(string segmentName, string[] segmentDetails) { const string firstSegmentName = "ST"; string errorMsgs = string.Empty; IPluglet nextPluglet; string location = "EDIReader.CreateAndAddNewSegment"; Logger.Debug(location, "Adding {0} segment", segmentName); string missingMandatorySegments; nextPluglet = CurrentPluglet.GetSegmentPluglet(segmentName, segmentDetails, firstSegmentName, out missingMandatorySegments); // First add missing mandatory segment errors if (nextPluglet != null && !string.IsNullOrWhiteSpace(missingMandatorySegments)) { string error = string.Format("Missing mandatory segments ({0}) between {1} and {2}" , missingMandatorySegments, CurrentPluglet.Tag, segmentName); if (FatpipeDocumentInst.Errors == null) { FatpipeDocumentInst.Errors = new List <string>(); } FatpipeDocumentInst.Errors.Add(error); Logger.Error("EDIReader.CreateAndAddNewSegment", EventId.EDIReaderMissingMandatorySegment, "{0} - {1}", GetCurrentPosContext(), error); EdiErrorType errorType = nextPluglet.IsIgnore ? EdiErrorType.Warning : EdiErrorType.Error; foreach (string segment in missingMandatorySegments.Split(',')) { Errors.AddSegmentError(segmentName, X12ErrorCode.MandatorySegmentMissingCode , string.Format("{0} : {1}", X12ErrorCode.GetStandardSegmentErrorDescription(X12ErrorCode.MandatorySegmentMissingCode), segment) , SegmentNumber, this.CurrentSegmentStartPos, this.CurrentSegmentEndPos - 1, errorType); } } if (nextPluglet == null) { /* //TODO: Revisit following if condition - do we really want to ignore ISA/GS segment missing in schema? * if (segmentName != "ISA" && segmentName != "GS") * { * errors = string.Format("{0} segment not found in schema after {1}", segmentName, CurrentPluglet.Name); * * Logger.Error(location, EventId.EDIReaderUnknownSegment, "{0} - {1}", GetCurrentPosContext(), errors); * Errors.AddSegmentError(segmentName, X12ErrorCode.UnrecognizedSegmentIDCode * , X12ErrorCode.GetStandardSegmentErrorDescription(X12ErrorCode.UnrecognizedSegmentIDCode), SegmentNumber); * } */ //experimenting with unknown here above is actual //IPluglet unknown = new Pluglet("UNRECOGNIZED_SEGMENT", "Unknown Segment", PlugletType.Segment, CurrentPluglet.Parent); IPluglet unknown = new Pluglet( new PlugletInput() { Name = "UNRECOGNIZED_SEGMENT", Definition = "Unknown Segment", Type = PlugletType.Segment, Parent = CurrentPluglet.Parent, IsIgnore = false, AddToParent = false, IsTagSameAsName = true, }); // IPluglet x = new Pluglet("child"+i, "Unknown Data", PlugletType.Data, unknown); //unknown.Children.Add(x); //} //DocumentFragment newFragment = unknown.ConstructDocumentFragment(segmentDetails, false, EDIDelimiters, out errors); errorMsgs = string.Format("{0} segment not found in schema after {1}", segmentName, CurrentPluglet.Name); Errors.AddSegmentError(segmentName, X12ErrorCode.UnrecognizedSegmentIDCode , X12ErrorCode.GetStandardSegmentErrorDescription(X12ErrorCode.UnrecognizedSegmentIDCode), SegmentNumber , this.CurrentSegmentStartPos, this.CurrentSegmentEndPos - 1, EdiErrorType.Error); DocumentFragment newFragment = new DocumentFragment() { Pluglet = unknown, Children = new List <IDocumentFragment>(), }; IPluglet childPluglet = new Pluglet("Data", "Data", PlugletType.Data, null); DocumentFragment child = new DocumentFragment() { Parent = newFragment, Pluglet = childPluglet, Children = null, SequenceNumber = SegmentNumber, StartOffset = this.CurrentSegmentStartPos, EndOffset = this.CurrentSegmentEndPos - 1, }; newFragment.Children.Add(child); child.Value = CurrentSegment; if (newFragment == null) { errorMsgs = string.Format("{0} DocumentFragment creation failed. Errors: {1}", segmentName, errorMsgs); Logger.Error(location, EventId.EDIReaderDocFragmentCreation, "{0} - {1}", GetCurrentPosContext(), errorMsgs); //TODO: what should be the code here? //Errors.AddGenericError(segmentName, X12ErrorCode.??? } else { ((DocumentFragment)FatpipeDocumentInst.RootFragment).AddDocumentFragment(newFragment); // CurrentPluglet = newFragment.Pluglet; } //experimenting with unknown here } else { if (nextPluglet.RepetitionInfo.MaxOccurs == 0) { Errors.AddSegmentError(segmentName, X12ErrorCode.UnexpectedSegmentCode , string.Format("{0} : {1}", X12ErrorCode.GetStandardSegmentErrorDescription(X12ErrorCode.UnexpectedSegmentCode), nextPluglet.Tag) , SegmentNumber, this.CurrentSegmentStartPos, this.CurrentSegmentEndPos - 1, EdiErrorType.Error); } else { DocumentFragment newFragment = nextPluglet.ConstructDocumentFragment(segmentDetails, false, EDIDelimiters, SegmentNumber, this.CurrentSegmentStartPos, this.CurrentSegmentEndPos - 1, ref errors, out errorMsgs); if (newFragment == null) { //errorMsgs = string.Format("{0} DocumentFragment creation failed. Errors: {1}", segmentName, errorMsgs); Logger.Error(location, EventId.EDIReaderDocFragmentCreation, "{0} - {1}", GetCurrentPosContext(), errorMsgs); // TODO: Replace UnexpectedSegmentCode with appropriate one Errors.AddGenericError(segmentName, X12ErrorCode.UnexpectedSegmentCode, errorMsgs, SegmentNumber, this.CurrentSegmentStartPos, this.CurrentSegmentEndPos); } else { ((DocumentFragment)FatpipeDocumentInst.RootFragment).AddDocumentFragment(newFragment); CurrentPluglet = newFragment.Pluglet; } } } if (!string.IsNullOrEmpty(errorMsgs)) { if (FatpipeDocumentInst.Errors == null) { FatpipeDocumentInst.Errors = new List <string>(); } FatpipeDocumentInst.Errors.Add(errorMsgs); } }
private void ProcessSTSegment() { string location = "EDIReader.ProcessSTSegment"; string errors = string.Empty; Logger.Info(location, "Start - {0}", GetCurrentPosContext()); Stopwatch sw = new Stopwatch(); sw.Start(); LastState = EDIState.ST; int currentTransactionSetType; if (CurrentSegmentDetails == null || CurrentSegmentDetails.Length < 2 || int.TryParse(CurrentSegmentDetails[1], out currentTransactionSetType) == false) { InvalidTransactionSetCount++; //TODO: Add error Logger.Error(location, "{0} - Invalid segment - {1}", GetCurrentPosContext(), CurrentSegment); } else { // TODO: Optimization - Load DocumentPlug, reconstruct ISA and GA segment if transaction set type changed //if (PrevTransactionSetType != currentTransactionSetType) { // Make sure that ISA and GA fields are already present if (ISARecordFields == null || GSRecordFields == null) { throw new EDIReaderException( string.Format("ISA and GA segments should be present before ST segment. {0}", GetCurrentPosContext())); } if (ISARecordFields.Length != MaxISAFieldRecordCount || GSRecordFields.Length == 0) { throw new EDIReaderException( string.Format("ISA and GA segments length ({0}, {1}) does not match expected length ({2}, non-zero). {4}", ISARecordFields.Length, GSRecordFields.Length, MaxISAFieldRecordCount, GetCurrentPosContext())); } //TODO: For testing invoking DocumentPlugFactory.CreateEDIDocumentPlug if (FPManager == null) { DocumentPlug = DocumentPlugFactory.CreateEDIDocumentPlug(currentTransactionSetType, ISARecordFields); } else { DocumentPlug = CreateEDIDocumentPlug(currentTransactionSetType, ISARecordFields); } CurrentPluglet = DocumentPlug.RootPluglet; // Construct start segment list CurrentPluglet.InitializeStartSegmentList(); FatpipeDocumentInst.DocumentPlug = DocumentPlug; FatpipeDocumentInst.RootFragment = CurrentPluglet.ConstructDocumentFragment(null, null); // Construct ISA node CreateAndAddNewSegment(EDIState.ISA.ToString(), ISARecordFields); // Construct GS node CreateAndAddNewSegment(EDIState.GS.ToString(), GSRecordFields); GSSegmentProcessed = true; GSPluglet = CurrentPluglet; PrevTransactionSetType = currentTransactionSetType; } //else //{ // // Move to GS node to start new segment // CurrentPluglet = GSPluglet; // // Remove previous TransactionSet // if (FatpipeDocumentInst.RootFragment.Children != null) // { // IDocumentFragment transactionSetChild = FatpipeDocumentInst.RootFragment.Children.Any( c => c.Pluglet.Tag == "TransactionSet"); // FatpipeDocumentInst.RootFragment.Children.Remove(transactionSetChild); // } // // Set errors to null // FatpipeDocumentInst.Errors = null; //} // Construct ST node CreateAndAddNewSegment(EDIState.ST.ToString(), CurrentSegmentDetails); } sw.Stop(); Logger.Info(location, "Stop - {0}. Elapsed time {1} ms", GetCurrentPosContext(), sw.ElapsedMilliseconds); }
// Return value indicate if ST segment is valid or not private bool ProcessSTSegment() { string location = "EDIReader.ProcessSTSegment"; string errors = string.Empty; Stopwatch sw = new Stopwatch(); sw.Start(); LastState = EDIState.ST; int currentTransactionSetType; if (CurrentSegmentDetails == null || CurrentSegmentDetails.Length < 2 || int.TryParse(CurrentSegmentDetails[1], out currentTransactionSetType) == false) { InvalidTransactionSetCount++; //TODO: Add error Logger.Error(location, EventId.EDIReaderInvalidSegment, "{0} - Invalid segment - {1}", GetCurrentPosContext(), CurrentSegment); Errors.AddSegmentError(CurrentSegment, X12ErrorCode.UnexpectedSegmentCode , X12ErrorCode.GetStandardSegmentErrorDescription(X12ErrorCode.UnexpectedSegmentCode), SegmentNumber , this.CurrentSegmentStartPos, this.CurrentSegmentEndPos - 1, EdiErrorType.Error); } else { ValidTransactionSetCount++; // TODO: Optimization - Load DocumentPlug, reconstruct ISA and GA segment if transaction set type changed //if (PrevTransactionSetType != currentTransactionSetType) { // Make sure that ISA and GA fields are already present if (ISARecordFields == null || GSRecordFields == null) { throw new EDIReaderException( string.Format("ISA and GA segments should be present before ST segment. {0}", GetCurrentPosContext())); } if (ISARecordFields.Length != MaxISAFieldRecordCount || GSRecordFields.Length == 0) { throw new EDIReaderException( string.Format("ISA and GA segments length ({0}, {1}) does not match expected length ({2}, non-zero). {3}", ISARecordFields.Length, GSRecordFields.Length, MaxISAFieldRecordCount, GetCurrentPosContext())); } //TODO: For testing invoking DocumentPlugFactory.CreateEDIDocumentPlug if (DocumentPlug == null) { if (FPManager == null) { DocumentPlug = DocumentPlugFactory.CreateEDIDocumentPlug(currentTransactionSetType); } else { DocumentPlug = CreateEDIDocumentPlug(currentTransactionSetType, ISARecordFields); } } else // Make sure that DocumentPlug and ST document type match { // DocumentPlug.DocumentType = 0 indicates that there was problem retrieving DocumentType // while constructing DocumentPlug if (DocumentPlug.DocumentType != 0 && DocumentPlug.DocumentType != currentTransactionSetType) { string errorDescription = "Spec Cert relates to document {0}, however ST01 value is {1}.; test File is rejected"; errorDescription = string.Format(errorDescription, DocumentPlug.DocumentType, currentTransactionSetType); FieldError fieldError = DataTypeHelper.GenerateFieldError(X12ErrorCode.DeInvalidCodeValueCode, errorDescription, CurrentSegmentDetails[0]); long currentSegmentFieldStartIndex = this.CurrentSegmentStartPos + 3; // length of "ST<delimiter>" long currentSegmentFieldEndIndex = currentSegmentFieldStartIndex + CurrentSegmentDetails[1].Length - 1; Logger.Error(location, EventId.EDIReaderInvalidTransactionSetType, errorDescription); Errors.AddFieldError(CurrentSegmentDetails[0], "ST01", fieldError.ErrorCode, fieldError.Description, SegmentNumber, 1, CurrentSegmentDetails[1], currentSegmentFieldStartIndex, currentSegmentFieldEndIndex, EdiErrorType.Error); return(false); } } CurrentPluglet = DocumentPlug.RootPluglet; CurrentPluglet.ResetCurrentOccurances(); // Construct start segment list CurrentPluglet.InitializeStartSegmentList(); FatpipeDocumentInst.TransactionSetType = currentTransactionSetType; if (CurrentSegmentDetails.Length > 2) { FatpipeDocumentInst.TransactionNumber = CurrentSegmentDetails[2]; } FatpipeDocumentInst.DocumentPlug = DocumentPlug; FatpipeDocumentInst.RootFragment = CurrentPluglet.ConstructDocumentFragment(null, null); // Construct ISA node //CreateAndAddNewSegment(EDIState.ISA.ToString(), ISARecordFields); // Construct GS node //CreateAndAddNewSegment(EDIState.GS.ToString(), GSRecordFields); //GSSegmentProcessed = true; //GSPluglet = CurrentPluglet; PrevTransactionSetType = currentTransactionSetType; } //else //{ // // Move to GS node to start new segment // CurrentPluglet = GSPluglet; // // Remove previous TransactionSet // if (FatpipeDocumentInst.RootFragment.Children != null) // { // IDocumentFragment transactionSetChild = FatpipeDocumentInst.RootFragment.Children.Any( c => c.Pluglet.Tag == "TransactionSet"); // FatpipeDocumentInst.RootFragment.Children.Remove(transactionSetChild); // } // // Set errors to null // FatpipeDocumentInst.Errors = null; //} // Construct ST node CreateAndAddNewSegment(EDIState.ST.ToString(), CurrentSegmentDetails); } sw.Stop(); Logger.Debug(location, "Stop - {0}. Elapsed time {1} ms", GetCurrentPosContext(), sw.ElapsedMilliseconds); return(true); }
/// <summary> /// Return flat file input and construct IFatpipeDocument /// IFatpipeDocument will NOT contain ISA and GA segments as it's not /// present in case of flat file. /// Since ISA segment is missing and there is no speific ST segment /// DocumentPlug is mandatory parameter. /// </summary> /// <returns></returns> public IFatpipeDocument ReadFile(Stream flatFileStream, IDocumentPlug documentPlug) { if (flatFileStream == null) { throw new ArgumentNullException("flatFileStream", "Flat file stream cannot be null"); } if (documentPlug == null) { throw new ArgumentNullException("documentPlug", "Document plug cannot be null"); } string location = "FlatFileReader.ReadFile"; Logger.Debug(location, "Start"); Stopwatch sw = new Stopwatch(); sw.Start(); errors = new InterchangeErrors(); DocumentPlug = documentPlug; long orgStartPos = flatFileStream.Position; FlatFileDelimiters = InitializeDelimiters(documentPlug); SegmentDelimiter = ((char)FlatFileDelimiters.SegmentDelimiter).ToString(); FormattedSegmentDelimiter = SegmentDelimiter; bool crLFPresent = FlatFileDelimiters.SegmentDelimiter == Delimiters.CarriageReturn || FlatFileDelimiters.SegmentDelimiterSuffix1 == Delimiters.CarriageReturn; if (!crLFPresent) { FormattedSegmentDelimiter = string.Format("{0}{1}", FormattedSegmentDelimiter, Environment.NewLine); } SegmentNumberFromStart = 0; CurrentSegmentStartPos = 0; this.DocumentReader = new StreamReader(flatFileStream, Encoding.UTF8); // Since flat file doesn't have concept of ST/SE, ans we want to use InterchangeErrors for reporting purpose // create dummy transaction set details Errors.AddTransactionSetDetails(1, "", "", true); CurrentPluglet = DocumentPlug.RootPluglet; CurrentPluglet.ResetCurrentOccurances(); // do we need this for flat files? CurrentPluglet.InitializeStartSegmentList(); FatpipeDocumentInst = new FatpipeDocument(); //FatpipeDocumentInst.TransactionSetType = ???; FatpipeDocumentInst.DocumentPlug = DocumentPlug; FatpipeDocumentInst.RootFragment = CurrentPluglet.ConstructDocumentFragment(null, null); while ((CurrentSegmentDetails = ReadNextSegment()) != null && CurrentSegmentDetails.Length > 0) { Logger.Debug(location, "{0} - Next segment {1}", GetCurrentPosContext(), CurrentSegmentDetails[0]); CreateAndAddNewSegment(CurrentSegmentDetails[0], CurrentSegmentDetails); if (string.IsNullOrWhiteSpace(FatpipeDocumentInst.OriginalPayload)) { FatpipeDocumentInst.OriginalPayload = CurrentSegment; } else { FatpipeDocumentInst.OriginalPayload += SegmentDelimiter + CurrentSegment; } if (string.IsNullOrWhiteSpace(FatpipeDocumentInst.BeautifiedOriginalPayloadBody)) { FatpipeDocumentInst.BeautifiedOriginalPayloadBody = CurrentSegment; } else { FatpipeDocumentInst.BeautifiedOriginalPayloadBody += FormattedSegmentDelimiter + CurrentSegment; } } sw.Stop(); Logger.Debug(location, "Stop - Elapsed time {0} ms", sw.ElapsedMilliseconds); return(FatpipeDocumentInst); }