Esempio n. 1
0
        /// <summary>
        /// Initialize EDIReader with a stream. Verify that stream contains EDI document (ISA segment).
        /// </summary>
        /// <param name="stream"></param>
        /// <returns>true if EDI document otherwise false</returns>
        public bool Initialize(Stream stream, IFatpipeManager fatpipeManager)
        {
            Logger.Info("EDIReader.Initialize", "Start");

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

            Stopwatch sw = new Stopwatch();

            sw.Start();

            FPManager = fatpipeManager;

            long orgStartPos = stream.Position;

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

            CurrentSegmentNumber     = 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);

                CurrentSegmentNumber = 1;

                this.DocumentReader = new StreamReader(stream, Encoding.UTF8);
                //TODO: Why is seek required here?
                this.DocumentReader.BaseStream.Seek(tokenizer.ISARecordLen + orgStartPos, SeekOrigin.Begin);
                FatpipeDocumentInst = new FatpipeDocument();

                SegmentDelimiter = ((char)EDIDelimiters.SegmentDelimiter).ToString();
            }
            else
            {
                ISASegment = string.Empty;
            }

            LastState = EDIState.ISA;

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

            return(isValidEDIDocument);
        }
        /// <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);
        }
Esempio n. 3
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);
        }
Esempio n. 4
0
        public static IFatpipeDocument Transform(IFatpipeDocument sourceDocument, ITransformPlug transformPlug)
        {
            if (sourceDocument == null)
            {
                throw new ArgumentNullException("sourceDocument");
            }

            Stopwatch sw = new Stopwatch();

            sw.Start();

            FatpipeDocument targetDocument = new FatpipeDocument();

            targetDocument.RootFragment = transformPlug.TargetDocument.RootPluglet.ConstructDocumentFragment(null, null);;

            //TODO: Handle loops
            foreach (ITransformGroup transformGroup in transformPlug.Facets)
            {
                Logger.Debug("DocumentTransformer.Transform", "Processing {0} tranformGroup", transformGroup.Name);

                foreach (ITransformLink transformLink in transformGroup.Links)
                {
                    Logger.Debug("DocumentTransformer.Transform", "Processing Link#-{0}: {1} [{2}] => {3} [{4}]"
                                 , transformLink.Name
                                 , transformLink.Source.ReferenceType, transformLink.Source.Name
                                 , transformLink.Target.ReferenceType, transformLink.Target.Name);

                    //TODO: Handle all kind of transformation
                    if (transformLink.Source.ReferenceType == ReferenceType.Document &&
                        transformLink.Target.ReferenceType == ReferenceType.Document)
                    {
                        // Traverse source path
                        IDocumentFragment sourceFragment = sourceDocument.RootFragment.MoveTo(transformLink.Source.Name);
                        if (sourceFragment != null)
                        {
                            IPluglet targetPluglet = targetDocument.RootFragment.Pluglet.MoveTo(transformLink.Target.Name);

                            if (targetPluglet != null)
                            {
                                Logger.Debug("DocumentTransformer.Transform", "Source = {0}, Target = {1}", sourceFragment.Name, targetPluglet.Tag);

                                Dictionary <string, string> attributes = new Dictionary <string, string>();
                                foreach (IPluglet attr in targetPluglet.Attributes)
                                {
                                    string attributeName = attr.Name;
                                    attributeName.Remove(0, 1);
                                    attributeName.Remove(attributeName.Length, 1);
                                    attributes.Add(attributeName, attributeName);
                                }

                                bool   isAttribute = false;
                                string name        = transformLink.Target.Name.Substring(
                                    transformLink.Target.Name.LastIndexOf(targetPluglet.PathSeperator) + targetPluglet.PathSeperator.Length);
                                // Check if this transformation point to attribute or leaf node
                                if (targetPluglet.Attributes != null && attributes.ContainsKey(name))
                                {
                                    isAttribute = true;
                                }

                                if (isAttribute == false)
                                {
                                    IDocumentFragment newFragment = targetPluglet.ConstructDocumentFragment(null, sourceFragment.Value);
                                    ((DocumentFragment)targetDocument.RootFragment).AddDocumentFragment(newFragment);
                                }
                                else
                                {
                                    ((DocumentFragment)targetDocument.RootFragment).AddDocumentFragment(transformLink.Target.Name, sourceFragment.Value);
                                }
                            }
                            else
                            {
                                string error = string.Format("Link#-{0}: {1} path not found in target tree", transformLink.Name, transformLink.Target.Name);
                                if (targetDocument.Errors == null)
                                {
                                    targetDocument.Errors = new List <string>();
                                }
                                targetDocument.Errors.Add(error);

                                Logger.Error("DocumentTransformer.Transform", EventId.DocTransformerNoMapping, error);
                            }
                        }
                    }
                    else
                    {
                        Logger.Debug("DocumentTransformer.Transform", "Ignoring Link#-{0}", transformLink.Name);
                    }
                }

                //TODO: Handle transformGroup.Formulas
            }

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

            return(targetDocument);
        }
        /// <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);
        }