Пример #1
0
        /// <summary>
        /// Return next EDI transaction set.
        /// IFatpipeDocument will contain ISA, GA and 1 ST segment
        /// </summary>
        /// <returns></returns>
        public IFatpipeDocument GetNextTransactionSet()
        {
            if (DocumentReader == null)
            {
                throw new EDIReaderException("Initialize API should be invoked successfully before calling GetNextTransactionSet");
            }

            string    location = "EDIReader.GetNextTransactionSet";
            Stopwatch sw       = new Stopwatch();

            sw.Start();

            Logger.Debug(location, "Start - {0}", GetCurrentPosContext());

            bool isTransactionSetFinished = false;

            while (isTransactionSetFinished == false &&
                   (CurrentSegmentDetails = ReadNextSegment()) != null &&
                   CurrentSegmentDetails.Length > 0)
            {
                Logger.Debug(location, "{0} - Next segment {1}", GetCurrentPosContext(), CurrentSegmentDetails[0]);

                EDIState nextState = GetEDIState(CurrentSegmentDetails[0]);

                switch (nextState)
                {
                case EDIState.GS:
                    if (!(LastState == EDIState.ISA || LastState == EDIState.GE))
                    {
                        throw new EDIReaderException(string.Format("GS segment should appear only after ISA or GE. {1}", GetCurrentPosContext()));
                    }

                    //Just set GSRecordFields, GS node will be constructed on first ST node
                    GSRecordFields     = CurrentSegmentDetails;
                    GSSegmentProcessed = false;

                    GSSegment = CurrentSegment;
                    FunctionalGroupNumber++;

                    // TODO: What is functionalId and ControlNumber? - set second and third parameter below
                    Errors.AddFunctionalGroupDetails(FunctionalGroupNumber, "", "", true);
                    break;

                case EDIState.GE:
                    // TODO: Remove GS check here in case empty GS segment is not valid scenario
                    if (!(LastState == EDIState.GS || LastState == EDIState.SE))
                    {
                        throw new EDIReaderException(string.Format("GE segment should appear only after GS or SE. {1}", GetCurrentPosContext()));
                    }

                    //TODO: Add validation of GE segment details values
                    //CheckForMissingSegments(CurrentSegmentDetails[0]);
                    break;

                case EDIState.ST:
                    if (!(LastState == EDIState.GS || LastState == EDIState.SE))
                    {
                        throw new EDIReaderException(string.Format("ST segment should appear only after GS or SE. {1}", GetCurrentPosContext()));
                    }

                    // Do not reset SegmentNumber as it's being used as over all segment number in EdiValidator for position
                    //SegmentNumber = 0;
                    TransactionSetNumber++;

                    // TODO: What is functionalId and ControlNumber? - set second and third parameter below
                    Errors.AddTransactionSetDetails(TransactionSetNumber, "", "", true);

                    FatpipeDocumentInst.BeautifiedOriginalPayloadBody = string.Empty;
                    TransactionSegment          = CurrentSegment;
                    FormattedTransactionSegment = CurrentSegment;

                    // If ST segment is not valid then move file reading pointer to SE segment
                    if (ProcessSTSegment() == false)
                    {
                        MoveToSESegment();
                        isTransactionSetFinished = true;
                        nextState = EDIState.SE;
                    }

                    break;

                case EDIState.SE:
                    if (!(LastState == EDIState.ST || LastState == EDIState.Other))
                    {
                        throw new EDIReaderException(string.Format("{0} segment should appear only after ST or Other. {1}", LastState, GetCurrentPosContext()));
                    }

                    //CheckForMissingSegments(CurrentSegmentDetails[0]);
                    CreateAndAddNewSegment(CurrentSegmentDetails[0], CurrentSegmentDetails);

                    //TODO: Add validation of SE segment details values

                    isTransactionSetFinished = true;

                    TransactionSegment          = TransactionSegment + SegmentDelimiter + CurrentSegment;
                    FormattedTransactionSegment = FormattedTransactionSegment + FormattedSegmentDelimiter + CurrentSegment;

                    //ValidateContingencies();
                    break;

                case EDIState.Other:
                    if (!(LastState == EDIState.ST || LastState == EDIState.Other))
                    {
                        throw new EDIReaderException(string.Format("{0} segment should appear only after ST or Other. {1}", LastState, GetCurrentPosContext()));
                    }

                    //Console.WriteLine("segment = " + CurrentSegmentDetails[0]);
                    CreateAndAddNewSegment(CurrentSegmentDetails[0], CurrentSegmentDetails);

                    TransactionSegment          = TransactionSegment + SegmentDelimiter + CurrentSegment;
                    FormattedTransactionSegment = FormattedTransactionSegment + FormattedSegmentDelimiter + CurrentSegment;
                    break;

                case EDIState.IEA:

                    //TODO: Add validation of IEA segment details values
                    break;
                }

                LastState = nextState;
            }

            // Construct original payload
            if (isTransactionSetFinished == true)
            {
                FatpipeDocumentInst.OriginalPayload  = ISASegment + SegmentDelimiter;
                FatpipeDocumentInst.OriginalPayload += GSSegment + SegmentDelimiter;
                FatpipeDocumentInst.OriginalPayload += TransactionSegment + SegmentDelimiter;
                FatpipeDocumentInst.OriginalPayload += "GE" + EDIDelimiters.FieldSeperator + "1" + EDIDelimiters.FieldSeperator + "1" + SegmentDelimiter;
                FatpipeDocumentInst.OriginalPayload += "IEA" + EDIDelimiters.FieldSeperator + "1" + EDIDelimiters.FieldSeperator + "1" + SegmentDelimiter;

                FatpipeDocumentInst.BeautifiedOriginalPayloadStartHeader  = ISASegment + FormattedSegmentDelimiter;
                FatpipeDocumentInst.BeautifiedOriginalPayloadStartHeader += GSSegment + FormattedSegmentDelimiter;
                FatpipeDocumentInst.BeautifiedOriginalPayloadBody        += FormattedTransactionSegment + FormattedSegmentDelimiter;
                FatpipeDocumentInst.BeautifiedOriginalPayloadEndHeader    = "GE" + EDIDelimiters.FieldSeperator + "1" + EDIDelimiters.FieldSeperator + "1" + FormattedSegmentDelimiter;
                FatpipeDocumentInst.BeautifiedOriginalPayloadEndHeader   += "IEA" + EDIDelimiters.FieldSeperator + "1" + EDIDelimiters.FieldSeperator + "1" + FormattedSegmentDelimiter;
            }

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

            return(isTransactionSetFinished == true ? FatpipeDocumentInst : null);
        }
Пример #2
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);
        }
Пример #3
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);
        }