コード例 #1
0
        public static void AddTransactionSetDetails(this InterchangeErrors errors, int tsNumber, string idCode, string ctrlNumber, bool updateExisting)
        {
            TransactionSetErrors transactionSetErrors = new TransactionSetErrors(tsNumber, idCode, ctrlNumber, new EdiSectionErrors());

            FunctionalGroupErrors functionalGroupErrors;

            if (errors.FunctionalGroupErrors.Count == 0)
            {
                // TODO: Handle this error condition properly - Need to consider scenario where ST segment appear before GS
                // this should be error since TransactionSetDetails should be added only after functionalGroup

                functionalGroupErrors = errors.CreateNewFunctionalGroupErrorInfo(-1, "---", "----");
            }
            else
            {
                functionalGroupErrors = errors.FunctionalGroupErrors.Last();
            }

            if (functionalGroupErrors.TransactionSetErrors.Count > 0 && updateExisting == true)
            {
                functionalGroupErrors.TransactionSetErrors.Clear();
            }

            functionalGroupErrors.TransactionSetErrors.Add(transactionSetErrors);
        }
コード例 #2
0
        public static void AddFunctionalGroupDetails(this InterchangeErrors errors, int groupNumber, string idCode, string ctrlNumber, bool updateExisting)
        {
            FunctionalGroupErrors functionalGroupErrors = new FunctionalGroupErrors(groupNumber, idCode, ctrlNumber);

            if (errors.FunctionalGroupErrors.Count > 0 && updateExisting == true)
            {
                errors.FunctionalGroupErrors.Clear();
            }

            errors.FunctionalGroupErrors.Add(functionalGroupErrors);
        }
コード例 #3
0
        public static void AddGenericError(this InterchangeErrors errors, string segmentName, int errorCode, string errorDescription)
        {
            if (errors == null)
            {
                throw new ArgumentNullException("errors");
            }

            GenericError genericError = new GenericError(errorCode, errorDescription, segmentName);

            EdiSectionErrors ediSectionErrors = GetEdiSectionErrors(errors, segmentName);

            ediSectionErrors.GenericErrorList.Add(genericError);
        }
コード例 #4
0
        public static void AddSegmentError(this InterchangeErrors errors, string segmentName, int errorCode, string errorDescription, int segmentNumber)
        {
            if (errors == null)
            {
                throw new ArgumentNullException("errors");
            }

            string       explicitLoopId = "";
            SegmentError segmentError   = new SegmentError(segmentName, segmentNumber, errorCode, errorDescription, explicitLoopId);

            EdiSectionErrors ediSectionErrors = GetEdiSectionErrors(errors, segmentName);

            ediSectionErrors.SegmentErrorList.Add(segmentError);
        }
コード例 #5
0
        private static EdiSectionErrors GetEdiSectionErrors(InterchangeErrors errors, string segmentName)
        {
            EdiSectionErrors ediSectionErrors;

            switch (segmentName.ToUpper())
            {
            case "ISA":
            case "IEA":
                ediSectionErrors = errors.IsaIeaErrorList;
                break;

            case "GS":
            case "GE":
                // FunctionalGroupErrors will have at least 1 element when GS segment is parsed.
                // If we encounter error during GS segment itself then add error in ISaIeaErrorList
                if (errors.FunctionalGroupErrors.Count == 0)
                {
                    ediSectionErrors = errors.IsaIeaErrorList;
                }
                else
                {
                    ediSectionErrors = errors.FunctionalGroupErrors.Last().GsGeErrorList;
                }
                break;

            default:
                // FunctionalGroupErrors will have at least 1 element when GS segment is parsed.
                // Similararly TransactionSetErrors will have at least 1 element when ST segment is parsed.
                // If we encounter error during any segment and then check the order in reverse way
                if (errors.FunctionalGroupErrors.Count == 0)
                {
                    ediSectionErrors = errors.IsaIeaErrorList;
                }
                else if (errors.FunctionalGroupErrors.Last().TransactionSetErrors.Count == 0)
                {
                    ediSectionErrors = errors.FunctionalGroupErrors.Last().GsGeErrorList;
                }
                else
                {
                    ediSectionErrors = errors.FunctionalGroupErrors.Last().TransactionSetErrors.Last().TsErrorList;
                }
                break;
            }

            return(ediSectionErrors);
        }
コード例 #6
0
        public static void AddFieldError(this InterchangeErrors errors, string segmentName, int errorCode, string errorDescription, int positionInSegment, string fieldValue)
        {
            int    positionInField = -1;
            int    repetitionCount = 0;
            string refDesignator   = "";

            if (errors == null)
            {
                throw new ArgumentNullException("errors");
            }

            FieldError fieldError = new FieldError(positionInSegment, positionInField, repetitionCount, errorCode, errorDescription, fieldValue, refDesignator);

            EdiSectionErrors ediSectionErrors = GetEdiSectionErrors(errors, segmentName);

            ediSectionErrors.FieldErrorList.Add(fieldError);
        }
コード例 #7
0
        public static List <SegmentValidationResult> GetSegmentValidationResults(this InterchangeErrors ediErrors)
        {
            List <SegmentValidationResult> segmentValidationResults = new List <SegmentValidationResult>();

            if (ediErrors != null && ediErrors.Count > 0)
            {
                if (ediErrors.IsaIeaErrorList != null && ediErrors.IsaIeaErrorList.Count > 0)
                {
                    segmentValidationResults.AddRange(ediErrors.IsaIeaErrorList.GetSegmentValidationResults());
                }

                if (ediErrors.FunctionalGroupErrors != null && ediErrors.FunctionalGroupErrors.Count > 0)
                {
                    foreach (FunctionalGroupErrors functionalGroupErrors in ediErrors.FunctionalGroupErrors)
                    {
                        if (functionalGroupErrors.GsGeErrorList != null && functionalGroupErrors.GsGeErrorList.Count > 0)
                        {
                            segmentValidationResults.AddRange(functionalGroupErrors.GsGeErrorList.GetSegmentValidationResults());
                        }

                        if (functionalGroupErrors.TransactionSetErrors != null && functionalGroupErrors.TransactionSetErrors.Count > 0)
                        {
                            foreach (TransactionSetErrors transactionSetErrors in functionalGroupErrors.TransactionSetErrors)
                            {
                                if (transactionSetErrors.TsErrorList != null && transactionSetErrors.TsErrorList.Count > 0)
                                {
                                    segmentValidationResults.AddRange(transactionSetErrors.TsErrorList.GetSegmentValidationResults());
                                }
                            }
                        }
                    }
                }
            }

            return(segmentValidationResults);
        }
コード例 #8
0
        /// <summary>
        /// Read xml file and construct IFatpipeDocument.
        /// Xml file reader will traverse Xml files and for each element
        /// match it with current pluglet. If match fails then it tries to
        /// find matching pluglet (similar to X12).
        /// </summary>
        /// <returns></returns>
        public IFatpipeDocument ReadFile(Stream xmlFileStream, IDocumentPlug documentPlug)
        {
            if (xmlFileStream == null)
            {
                throw new ArgumentNullException("xmlFileStream", "Xml file stream cannot be null");
            }

            if (documentPlug == null)
            {
                throw new ArgumentNullException("documentPlug", "Document plug cannot be null");
            }

            string location = "XmlFileReader.ReadFile";

            Logger.Debug(location, "Start");

            BeautifiedOriginalPayload = string.Empty;
            CurrentElementNumber      = 0;
            TotalPayloadLength        = 0;
            CurrentLinePayloadStart   = 0;
            CurrentLinePayloadEnd     = 0;
            CurrentLevel = 0;
            Stopwatch sw = new Stopwatch();

            sw.Start();

            errors = new InterchangeErrors();

            // Since xml 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);

            IPluglet currentPluglet = documentPlug.RootPluglet;

            currentPluglet.ResetCurrentOccurances();
            currentPluglet.InitializeStartSegmentList();

            FatpipeDocumentInst = new FatpipeDocument();
            FatpipeDocumentInst.DocumentPlug = documentPlug;
            FatpipeDocumentInst.RootFragment = currentPluglet.ConstructDocumentFragment(null, null);

            IDocumentFragment currentDocumentFragment = FatpipeDocumentInst.RootFragment;
            IDocumentFragment newDocumentFragment     = null;

            bool isLeafNode = false;

            try
            {
                XmlTextReader xmlReader = new XmlTextReader(xmlFileStream);

                // If some element doesn't match document plutlet then stop
                // TODO: Should we try to match other elements? If yes, which pluglet to start with?
                // Also we need to ignore this entire element
                bool stopProcessing = false;

                while (xmlReader.Read())
                {
                    switch (xmlReader.NodeType)
                    {
                    case XmlNodeType.Element:
                        isLeafNode = false;
                        AddStartElementToPayload(xmlReader.Name, xmlReader.IsEmptyElement);

                        if (xmlReader.IsEmptyElement)
                        {
                            break;
                        }

                        if (stopProcessing == false)
                        {
                            currentDocumentFragment = ConstructNewDocumentFragment(xmlReader.Name, currentPluglet, currentDocumentFragment);
                        }

                        // If some element doesn't match document plutlet then stop
                        // TODO: Should we try to match other elements? If yes, which pluglet to start with?
                        // Also we need to ignore this entire element
                        if (currentDocumentFragment == null)
                        {
                            stopProcessing = true;
                        }
                        else
                        {
                            currentPluglet = currentDocumentFragment.Pluglet;
                        }

                        CurrentLevel++;
                        CurrentElementNumber++;
                        break;

                    case XmlNodeType.Text:
                        isLeafNode = true;
                        AddValueToPayload(xmlReader.Value);
                        if (stopProcessing == false)
                        {
                            currentDocumentFragment.Value = xmlReader.Value;
                        }
                        // Assumption: Leaf nodes are on same line and non-leaf nodes are 1-per line (separate line for start and end element)
                        // If this assumption is wrong then we can construct the xml in string format to match fulfill above assumption
                        // and then Ux can use this string version of xml to highlight the errors.
                        CurrentElementNumber--;     // Decrement since leaf level elements are one line, so we need to increment element on endElement only.
                        break;

                    case XmlNodeType.EndElement:
                        CurrentLevel--;
                        AddEndElementToPayload(xmlReader.Name, isLeafNode);
                        if (stopProcessing == false)
                        {
                            // Check if all mandatory segments were present
                            CheckMissingMandatoryElements(currentPluglet, currentDocumentFragment);
                            currentDocumentFragment = currentDocumentFragment.Parent;
                            currentPluglet          = currentPluglet.Parent;
                        }

                        CurrentElementNumber++;
                        isLeafNode = false;
                        break;

                    default:
                        break;
                    }
                }
            }
            catch (XmlException xmlException)
            {
                // TODO: Pass start and end postition
                Errors.AddGenericError(currentPluglet == null ? "N/A" : currentPluglet.Name, X12ErrorCode.UnexpectedSegmentCode,
                                       string.Format("Error parsing XML document: {0}", xmlException.Message),
                                       CurrentElementNumber / 2, CurrentLinePayloadStart + TotalPayloadLength, CurrentLinePayloadEnd + TotalPayloadLength);
            }
            catch (Exception exception)
            {
                // TODO: Pass start and end postition (for all Errors.Add* calls) in this file.
                Errors.AddGenericError(currentPluglet == null ? "N/A" : currentPluglet.Name, X12ErrorCode.UnexpectedSegmentCode,
                                       "Internal error occurred, please contact Maarg",
                                       CurrentElementNumber / 2, CurrentLinePayloadStart + TotalPayloadLength, CurrentLinePayloadEnd + TotalPayloadLength);
                Logger.Error(location, EventId.XmlReaderUnhandledException, "Error occured during xml file processing: {0}", exception.ToString());
            }

            FatpipeDocumentInst.BeautifiedOriginalPayloadBody = BeautifiedOriginalPayload;

            sw.Stop();
            Logger.Debug(location, "Stop - Elapsed time {0} ms", sw.ElapsedMilliseconds);

            return(FatpipeDocumentInst);
        }
コード例 #9
0
        /// <summary>
        /// Initialize EDIReader with a stream. Verify that stream contains EDI document (ISA segment).
        /// </summary>
        /// <param name="stream"></param>
        /// <param name="fatpipeManager"></param>
        /// <param name="documentPlug"></param>
        /// <returns>true if EDI document otherwise false</returns>
        public bool Initialize(Stream stream, IFatpipeManager fatpipeManager, IDocumentPlug documentPlug)
        {
            if (stream == null)
            {
                throw new ArgumentNullException("stream");
            }

            Stopwatch sw = new Stopwatch();

            sw.Start();

            Errors = new InterchangeErrors();

            FPManager    = fatpipeManager;
            DocumentPlug = documentPlug;

            long orgStartPos = stream.Position;

            Delimiters           delimiters;
            InterchangeTokenizer tokenizer = new InterchangeTokenizer(stream);
            bool isValidEDIDocument        = tokenizer.IsX12Interchange(out delimiters);

            FunctionalGroupNumber    = TransactionSetNumber = SegmentNumberFromStart = SegmentNumber = 0;
            ValidTransactionSetCount = InvalidTransactionSetCount = 0;
            PrevTransactionSetType   = 0;

            DocumentReader = null;
            if (isValidEDIDocument == true)
            {
                EDIDelimiters = delimiters;
                //TODO: Review following logic
                //Read ISA field till component separator - Do not include component separator
                ISASegment = tokenizer.ISARecord.Substring(0, tokenizer.ISARecord.IndexOf((char)EDIDelimiters.ComponentSeperator) + 1);

                //TODO: Suraj: confirm this special case - last value as data element separator
                ISARecordFields = ISASegment.Split((char)EDIDelimiters.FieldSeperator);

                SegmentNumberFromStart = 1;

                stream.Position     = orgStartPos;
                this.DocumentReader = new StreamReader(stream, Encoding.UTF8);
                //TODO: Why is seek required here?
                this.CurrentSegmentStartPos = 0;
                this.CurrentSegmentEndPos   = 0;
                //this.CurrentSegmentEndPos = this.CurrentSegmentStartPos + tokenizer.ISARecordLen - 1;
                //this.DocumentReader.BaseStream.Seek(this.CurrentSegmentEndPos + basePosition, SeekOrigin.Begin);
                FatpipeDocumentInst = new FatpipeDocument();
                FatpipeDocumentInst.BeautifiedOriginalPayloadStartHeader = string.Empty;
                FatpipeDocumentInst.BeautifiedOriginalPayloadBody        = string.Empty;
                FatpipeDocumentInst.BeautifiedOriginalPayloadEndHeader   = string.Empty;

                SegmentDelimiter          = ((char)EDIDelimiters.SegmentDelimiter).ToString();
                FormattedSegmentDelimiter = SegmentDelimiter;

                bool crLFPresent = delimiters.SegmentDelimiter == Delimiters.CarriageReturn || delimiters.SegmentDelimiterSuffix1 == Delimiters.CarriageReturn;
                if (!crLFPresent)
                {
                    FormattedSegmentDelimiter = string.Format("{0}{1}", FormattedSegmentDelimiter, Environment.NewLine);
                }

                Logger.Info("EDIReader.Initialize", "EDIDelimiters: SegmentDelimiter={0}, FieldSeperator={1}, ComponentSeperator={2}", (char)EDIDelimiters.SegmentDelimiter, (char)EDIDelimiters.FieldSeperator, (char)EDIDelimiters.ComponentSeperator);
            }
            else //invalid document code path
            {
                this.CurrentSegmentStartPos = orgStartPos;
                this.CurrentSegmentEndPos   = orgStartPos + 3;
                Logger.Error("EDIReader.Initialize", EventId.EDIReaderInvalidDocument, "EDI document is not valid. Error: {0}", tokenizer.Error);

                Errors.AddGenericError("ISA", SchemaErrorCode.SchemaCode100EInvalidDocType, tokenizer.Error, SegmentNumber, this.CurrentSegmentStartPos, this.CurrentSegmentEndPos);

                StringBuilder sb         = new StringBuilder();
                int           errorIndex = 1;
                Errors.IsaIeaErrorList.WriteError(sb, ref errorIndex);

                ISASegment = string.Empty;
            }

            LastState = EDIState.ISA;

            sw.Stop();
            Logger.Debug("EDIReader.Initialize", "Elapsed time {0} ms", sw.ElapsedMilliseconds);

            return(isValidEDIDocument);
        }
コード例 #10
0
        /// <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);
        }