/// <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);
        }
Exemple #2
0
        /// <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);
            }
        }