public EdiStream(Stream ediStream)
 {
     _streamReader = new StreamReader(ediStream);
     _interchangeContext = new InterchangeContext(_streamReader);
     ediStream.Position = 0;
     _streamReader.DiscardBufferedData();
 }
Exemple #2
0
        /// <summary>
        /// Initializes a new instance of the <see cref="SegmentContext"/> class.
        /// </summary>
        /// <param name="ediSegment">The edi segment.</param>
        /// <param name="interchangeContext">The interchange context.</param>
        /// <param name="format">The edi format.</param>
        public SegmentContext(string ediSegment, InterchangeContext interchangeContext, EdiFormats format)
        {
            if (string.IsNullOrEmpty(ediSegment)) throw new ArgumentNullException("ediSegment");
            if (interchangeContext == null) throw new ArgumentNullException("interchangeContext");

            // Blank segments shouldn't have gone that far
            var splitted = ediSegment.Split(interchangeContext.DataElementSeparator.ToCharArray(), StringSplitOptions.None);
            if (splitted.Length < 2) throw new Exception("Segment is blank.");

            Name = splitted[0];
            Value = null;
            ParentId = null;

            // UNA segments don't have values
            if (ediSegment.StartsWith(EdiSegments.Una))
            {
                Name = EdiSegments.Una;
            }

            // Handle blank segments, e.g. BHT+'
            if (format == EdiFormats.Hipaa)
            {
                var splittedElement = splitted[1].Split(interchangeContext.ComponentDataElementSeparator.ToCharArray(), StringSplitOptions.None);
                Value = splittedElement[0];
                if (ediSegment.StartsWith(EdiSegments.Hl) && !string.IsNullOrEmpty(splitted[2])) ParentId = splitted[2];
            }
        }
Exemple #3
0
 public EdiStream(Stream ediStream, string definitionsAssemblyName = null)
 {
     _streamReader = new StreamReader(ediStream);
     _interchangeContext = new InterchangeContext(_streamReader, definitionsAssemblyName);
     ediStream.Position = 0;
     _streamReader.DiscardBufferedData();
 }
        /// <summary>
        /// Lexical analysis of the message
        /// </summary>
        /// <param name="segments">The edi segments.</param>
        /// <param name="envelopes">The edi envelopes.</param>
        /// <param name="interchangeContext">The interchange context.</param>
        /// <returns>The pased edi message.</returns>
        public static Message Analyze(List<string> segments, List<string> envelopes, InterchangeContext interchangeContext)
        {
            // Read the message context from the envelope headers
            var messageContext = new MessageContext(envelopes, interchangeContext);

            // This will read through the grammar and will build an xml

            // Get the grammar from the context
            var messageGrammar = ParseTree.LoadFrom(messageContext.SystemType,
                pt => pt.IsMessage || pt.IsGroup || pt.IsChoice || pt.IsAll || pt.IsLoopOfLoops);
            // Set the position in the grammar
            var lastSegment = messageGrammar.Children.First();

            // Create the xml root of the parsed edi
            var ediXml = ToXml(messageGrammar, interchangeContext);
            // Set the position in the xml
            var lastXElement = ediXml;

            // Iterate trough the segment lines
            foreach (var segment in segments)
            {
                try
                {
                    // Find the next segment grammar
                    var currSeg = lastSegment.FindNextSegment(new SegmentFullName(segment, interchangeContext, messageContext.Format));
                    // Build the segment hierarchy
                    // This will move to the required level up for the segment parents: groups, choices, all and loop of loops,
                    // until another group is reached.
                    var segmentTree = GetSegmentTree(currSeg, lastSegment);
                    // Intersect the grammar with the parsed xml.
                    // The new chunk will be attched to this intersection point.
                    lastXElement = lastXElement.AncestorsAndSelf().Last(xe => xe.Name.LocalName == segmentTree.First().Parent.Name);

                    // Attach each bit
                    foreach (var parseTree in segmentTree)
                    {
                        // Parse if a segment, otherwise convert to xml
                        var element = parseTree.IsSegment
                            ? SegmentParser.ParseLine(parseTree, segment, interchangeContext)
                            : ToXml(parseTree, interchangeContext);

                        // Attach to the xml
                        lastXElement.Add(element);
                        // Set the last attached as the attachment point as we iterate from the top parent to the bottom segment
                        lastXElement = element;
                    }

                    // Reset the position in the grammar
                    lastSegment = currSeg;

                }
                catch (Exception ex)
                {
                    throw new ParserException("Failed at line: " + segment, ex);
                }
            }

            return new Message(ediXml, messageContext);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="MessageContext"/> class.
        /// </summary>
        /// <param name="envelopes">
        /// From interchange headers
        /// </param>
        /// <param name="interchangeContext">
        /// The interchange context
        /// </param>
        public MessageContext(IEnumerable<string> envelopes, InterchangeContext interchangeContext)
        {
            var context = ToContext(envelopes, interchangeContext);

            Format = context.Item4;
            Version = context.Item2;
            Tag = context.Item1;
            Origin = context.Item3;
            _systemType = ToSystemType(Format, Version, Tag, Origin);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="XmlLexer"/> class.
        /// </summary>
        /// <param name="xmlEdi">
        /// Edi as Xml
        /// </param>
        /// <param name="context">
        /// The interchange context
        /// </param>
        public ToEdiLexer(XElement xmlEdi, InterchangeContext context)
            : base(xmlEdi)
        {
            InterchangeContext = new InterchangeContext(EdiFormats.Edifact);
            // Merge the custom context to the default
            InterchangeContext.Merge(context);

            // Make sure no same separator is used more than once
            if (!InterchangeContext.IsValid(EdiFormats.Edifact))
                throw new ParserException("Invalid interchange context.");
        }
 //-----------------------------------------------------------------------------------------------------
 public void SaveEdi(string filename, string segmentTerminator = null)
 {
     var interchangeContext = new InterchangeContext
     {
         SegmentTerminator =
         segmentTerminator,
     };
     var parsedXml = _interchange.ToEdi(interchangeContext);
     using (TextWriter tw = File.CreateText(filename))
     {
         tw.Write(string.Concat(parsedXml));
     }
 }
        /// <summary>
        /// Splits a segment line into composite data elements
        /// </summary>
        /// <param name="ediSegment">The segment line</param>
        /// <param name="interchangeContext">The interchange context containing the separators</param>
        /// <returns>The collection of composite data elements</returns>
        public static string[] GetEdiCompositeDataElements(string ediSegment, InterchangeContext interchangeContext)
        {
            if (string.IsNullOrEmpty(ediSegment)) throw new ArgumentNullException("ediSegment");
            if (interchangeContext == null) throw new ArgumentNullException("interchangeContext");

            // Handle escapes
            // Retains blank lines
            var result = !string.IsNullOrEmpty(interchangeContext.ReleaseIndicator)
                                      ? ediSegment.EscapeSplit(interchangeContext.ReleaseIndicator[0],
                                                             interchangeContext.DataElementSeparator[0], StringSplitOptions.None)
                                      : ediSegment.Split(interchangeContext.DataElementSeparator.ToCharArray(),
                                                       StringSplitOptions.None);

            // Skip the segment name
            return result.Skip(1).ToArray();
        }
Exemple #9
0
        /// <summary>
        /// Gets the segment name from a segment line.
        /// </summary>
        /// <param name="ediSegment">The segment line.</param>
        /// <param name="interchangeContext">The interchange context containing the separators.</param>
        /// <returns>The segment name.</returns>
        public static string GetSegmentName(string ediSegment, InterchangeContext interchangeContext)
        {
            if (string.IsNullOrEmpty(ediSegment))
            {
                throw new ArgumentNullException("ediSegment");
            }
            if (interchangeContext == null)
            {
                throw new ArgumentNullException("interchangeContext");
            }
            if (ediSegment.StartsWith(EdiSegments.Una))
            {
                return(EdiSegments.Una);
            }

            return(ediSegment.Split(interchangeContext.DataElementSeparator.ToCharArray(), StringSplitOptions.None)[0]);
        }
Exemple #10
0
        /// <summary>
        /// Parses segment xml
        /// </summary>
        /// <param name="segment">The segment xml.</param>
        /// <param name="parseTree">The segment grammar.</param>
        /// <param name="interchangeContext">The interchange context.</param>
        /// <returns>The parsed line.</returns>
        private static string Parse(XElement segment, ParseTree parseTree, InterchangeContext interchangeContext)
        {
            // Start with the segment name
            // BHT+, etc.
            var result = parseTree.EdiName + interchangeContext.DataElementSeparator;

            // For all elements in the parse tree - append to the segment name to build the edi string
            // BHT+88, etc.
            // Parse according to the parse tree
            foreach (var element in parseTree.Children)
            {
                var currentElement = element;
                // Find the matching elemtns by name
                // If > 1 found, then there are repetitions
                var matchingElements = segment.Elements().Where(e => e.Name.LocalName == currentElement.Name);

                string line = string.Empty;
                foreach (var matchingElement in matchingElements)
                {
                    // Parse the element and split the repetitions
                    line = line + ParseElement(matchingElement, element, interchangeContext)
                           + interchangeContext.RepetitionSeparator;
                }

                // Make sure the trailing repetitions separator is removed
                // To avoid stripping the default repetitions separator in case there is something like 88:55::
                // The result should be 88:55:, therefore we can't just strip the trailing separators
                line = line.EndsWith(interchangeContext.RepetitionSeparator + interchangeContext.RepetitionSeparator)
                    ? line.Substring(0, line.Length - 1)
                    : line.TrimEnd(interchangeContext.RepetitionSeparator.ToCharArray());

                // Add to the segment string
                // BHT+88:55:+
                result = result + line + interchangeContext.DataElementSeparator;
            }

            // Remove the trailing data element separator
            // BHT+88:55:
            result = CleanupTrailingSeparators(result, interchangeContext.DataElementSeparator, interchangeContext); //result.TrimEnd(interchangeContext.DataElementSeparator.ToCharArray());
            // Append the segment terminator
            // BHT+88:55:'
            result = result + interchangeContext.SegmentTerminator;

            return(result);
        }
Exemple #11
0
        /// <summary>
        /// Converts EDI interchange headers into message context.
        /// </summary>
        /// <param name="envelopes">The interchange headers.</param>
        /// <param name="interchangeContext">The interchange context.</param>
        private void ToContextX12(IEnumerable <string> envelopes, InterchangeContext interchangeContext)
        {
            var    enumerable = envelopes as List <string> ?? envelopes.ToList();
            string version;
            string origin;
            string format;
            string tag;

            try
            {
                var gs = enumerable.Single(es => es.StartsWith(EdiSegments.Gs));
                var ediCompositeDataElementsGs = EdiHelper.GetEdiCompositeDataElements(gs, interchangeContext);

                version = ediCompositeDataElementsGs[7].Substring(0, 6);
                origin  = ediCompositeDataElementsGs[7].Count() >= 10
                    ? ediCompositeDataElementsGs[7].Substring(6, 4)
                    : null;
                format = HipaaHelper.IsHipaa(version + origin) ? EdiFormats.Hipaa.ToString() : EdiFormats.X12.ToString();

                if (!HipaaHelper.IsHipaa(version + origin))
                {
                    origin = null;
                }
            }
            catch (Exception ex)
            {
                throw new ParserException("Can't parse GS segment.", ex);
            }

            try
            {
                var st = enumerable.Single(es => es.StartsWith(EdiSegments.St));
                var ediCompositeDataElementsSt = EdiHelper.GetEdiCompositeDataElements(st, interchangeContext);
                tag = ediCompositeDataElementsSt[0];
            }
            catch (Exception ex)
            {
                throw new ParserException("Can't parse ST segment.", ex);
            }

            Tag     = tag;
            Version = version;
            Origin  = origin;
            Format  = ToFormat(format);
        }
Exemple #12
0
        /// <summary>
        /// Converts EDI interchange headers into message context.
        /// </summary>
        /// <param name="envelopes">The interchange headers.</param>
        /// <param name="interchangeContext">The interchange context.</param>
        private void ToContextEdifact(IEnumerable <string> envelopes, InterchangeContext interchangeContext)
        {
            try
            {
                var unh = envelopes.Single(es => es.StartsWith(EdiSegments.Unh));
                var ediCompositeDataElements = EdiHelper.GetEdiCompositeDataElements(unh, interchangeContext);
                var ediDataElements          = EdiHelper.GetEdiComponentDataElements(ediCompositeDataElements[1],
                                                                                     interchangeContext);

                Tag     = ediDataElements[0];
                Version = ediDataElements[1] + ediDataElements[2];
                Origin  = null;
                Format  = EdiFormats.Edifact;
            }
            catch (Exception ex)
            {
                throw new ParserException("Can't parse UNH segment.", ex);
            }
        }
Exemple #13
0
        /// <summary>
        /// Escapes a string value to be valid in xml
        /// </summary>
        /// <param name="dataElement">The xml element.</param>
        /// <param name="interchangeContext">The interchange context.</param>
        /// <returns>The valid xml value.</returns>
        private static string GetValidDataElementValue(XElement dataElement, InterchangeContext interchangeContext)
        {
            var dataElementValue = dataElement == null ? string.Empty : dataElement.Value;

            // Secure non valid XML symbols
            // Currently only &
            if (dataElementValue.Contains("&"))
            {
                var securityElement = SecurityElement.FromString("<parse>" + dataElementValue + "</parse>");
                if (securityElement == null)
                {
                    throw new ParserException("Can't parse value " + dataElementValue);
                }

                dataElementValue = securityElement.Text;
            }

            //  Escape all terminator symbols
            return(interchangeContext.EscapeLine(dataElementValue));
        }
Exemple #14
0
        /// <summary>
        /// Converts EDI interchange headers into message context.
        /// </summary>
        /// <param name="envelopes">The interchange headers.</param>
        /// <param name="interchangeContext">The interchange context.</param>
        private void ToContext(IEnumerable <string> envelopes, InterchangeContext interchangeContext)
        {
            if (envelopes == null)
            {
                throw new ArgumentNullException("envelopes");
            }

            switch (interchangeContext.Format)
            {
            case EdiFormats.Edifact:
                ToContextEdifact(envelopes, interchangeContext);
                break;

            case EdiFormats.X12:
                ToContextX12(envelopes, interchangeContext);
                break;

            default:
                throw new Exception(string.Format("Unsupported message format = {0}", interchangeContext.Format));
            }
        }
Exemple #15
0
        /// <summary>
        /// Initializes a new instance of the <see cref="SegmentContext"/> class.
        /// </summary>
        /// <param name="ediSegment">The edi segment.</param>
        /// <param name="interchangeContext">The interchange context.</param>
        /// <param name="format">The edi format.</param>
        public SegmentContext(string ediSegment, InterchangeContext interchangeContext, EdiFormats format)
        {
            if (string.IsNullOrEmpty(ediSegment))
            {
                throw new ArgumentNullException("ediSegment");
            }
            if (interchangeContext == null)
            {
                throw new ArgumentNullException("interchangeContext");
            }

            // Blank segments shouldn't have gone that far
            var splitted = ediSegment.Split(interchangeContext.DataElementSeparator.ToCharArray(), StringSplitOptions.None);

            if (splitted.Length < 2)
            {
                throw new Exception("Segment is blank.");
            }

            Name     = splitted[0];
            Value    = null;
            ParentId = null;

            // UNA segments don't have values
            if (ediSegment.StartsWith(EdiSegments.Una))
            {
                Name = EdiSegments.Una;
            }

            // Handle blank segments, e.g. BHT+'
            if (format == EdiFormats.Hipaa && !splitted[1].Contains(interchangeContext.ComponentDataElementSeparator))
            {
                Value = splitted[1];
                if (ediSegment.StartsWith(EdiSegments.Hl) && !string.IsNullOrEmpty(splitted[2]))
                {
                    ParentId = splitted[2];
                }
            }
        }
Exemple #16
0
        /// <summary>
        /// Splits a segment line into composite data elements
        /// </summary>
        /// <param name="ediSegment">The segment line</param>
        /// <param name="interchangeContext">The interchange context containing the separators</param>
        /// <returns>The collection of composite data elements</returns>
        public static string[] GetEdiCompositeDataElements(string ediSegment, InterchangeContext interchangeContext)
        {
            if (string.IsNullOrEmpty(ediSegment))
            {
                throw new ArgumentNullException("ediSegment");
            }
            if (interchangeContext == null)
            {
                throw new ArgumentNullException("interchangeContext");
            }

            // Handle escapes
            // Retains blank lines
            var result = !string.IsNullOrEmpty(interchangeContext.ReleaseIndicator)
                                      ? ediSegment.EscapeSplit(interchangeContext.ReleaseIndicator[0],
                                                               interchangeContext.DataElementSeparator[0], StringSplitOptions.None)
                                      : ediSegment.Split(interchangeContext.DataElementSeparator.ToCharArray(),
                                                         StringSplitOptions.None);

            // Skip the segment name
            return(result.Skip(1).ToArray());
        }
        /// <summary>
        /// Splits an Edi messages into a collection of segments
        /// </summary>
        /// <param name="contents">The edi message</param>
        /// <param name="interchangeContext">The interchange context containing the separators</param>
        /// <returns>The collection of segments</returns>
        public static string[] GetEdiSegments(string contents, InterchangeContext interchangeContext)
        {
            if (contents == null) throw new ArgumentNullException("contents");
            if (interchangeContext == null) throw new ArgumentNullException("interchangeContext");

            // Handle carriage return\new line separator
            if (interchangeContext.SegmentTerminator != Environment.NewLine)
                contents = contents.Replace(Environment.NewLine, string.Empty);

            // Handle escape segment separator
            // Removes blank lines
            var result = !string.IsNullOrEmpty(interchangeContext.ReleaseIndicator)
                ? contents.EscapeSplit(interchangeContext.ReleaseIndicator[0],
                    interchangeContext.SegmentTerminator[0],
                    StringSplitOptions.RemoveEmptyEntries)
                : contents.Split(interchangeContext.SegmentTerminator.ToCharArray(),
                    StringSplitOptions.RemoveEmptyEntries);

            result = (from r in result select r.Trim()).ToArray();
            return result;

        }
Exemple #18
0
        public void TestToEdiWithInvalidContext()
        {
            // ARRANGE
            const string sample             = "EdiFabric.Tests.Xml.X12_810_00204.xml";
            var          interchangeContext = new InterchangeContext
            {
                DataElementSeparator          = "*",
                ComponentDataElementSeparator = "*"
            };

            // ACT
            try
            {
                Interchange.LoadFrom(
                    XElement.Load(Assembly.GetExecutingAssembly().GetManifestResourceStream(sample))).ToEdi(interchangeContext);
            }
            catch (Exception ex)
            {
                // ASSERT
                Assert.IsInstanceOfType(ex, typeof(ParserException));
                Assert.IsTrue(ex.Message.StartsWith("Invalid interchange context"));
            }
        }
Exemple #19
0
        /// <summary>
        /// Converts edi interchange headers into message context.
        /// </summary>
        /// <param name="envelopes">The interchange headers.</param>
        /// <param name="interchangeContext">The interchange context.</param>
        private void ToContext(IEnumerable<string> envelopes, InterchangeContext interchangeContext)
        {
            if (envelopes == null) throw new ArgumentNullException("envelopes");

            switch (interchangeContext.Format)
            {
                case EdiFormats.Edifact:
                    ToContextEdifact(envelopes, interchangeContext);
                    break;
                case EdiFormats.X12:
                    ToContextX12(envelopes, interchangeContext);
                    break;
                default:
                    throw new Exception(string.Format("Unsupported message format = {0}", interchangeContext.Format));
            }
        }
Exemple #20
0
        /// <summary>
        /// Parses data element xml
        /// </summary>
        /// <param name="dataElement">The dataelement xml.</param>
        /// <param name="parseTree">The dataelement grammar.</param>
        /// <param name="interchangeContext">The interchange context.</param>
        /// <returns>The parsed line.</returns>
        private static string ParseElement(XElement dataElement, ParseTree parseTree, InterchangeContext interchangeContext)
        {
            if (parseTree.IsComplex)
            {
                var line = string.Empty;
                // If complex data element, build a line from all the children in the parse tree
                foreach (var element in parseTree.Children)
                {
                    // Can be only one match
                    // If the XML contains data element that is not defined in the class, it will be skipped
                    // This way only know data elements will be parsed
                    var matchingElement =
                        dataElement.Elements().SingleOrDefault(e => e.Name.LocalName == element.Name);

                    // Build the line
                    line = line +
                           GetValidDataElementValue(matchingElement, interchangeContext) +
                           interchangeContext.ComponentDataElementSeparator;
                }

                // Remove the trailing composite terminator
                return(CleanupTrailingSeparators(line, interchangeContext.ComponentDataElementSeparator, interchangeContext));
                //return line.TrimEnd(interchangeContext.ComponentDataElementSeparator.ToCharArray());
            }

            // If simple just escape the value
            return(GetValidDataElementValue(dataElement, interchangeContext));
        }
 /// <summary>
 /// Gets the segment name from a segment line
 /// </summary>
 /// <param name="ediSegment">The segment line</param>
 /// <param name="interchangeContext">The interchange context containing the separators</param>
 /// <returns>The segment name</returns>
 public static string GetSegmentName(string ediSegment, InterchangeContext interchangeContext)
 {
     if (string.IsNullOrEmpty(ediSegment)) throw new ArgumentNullException("ediSegment");
     if (interchangeContext == null) throw new ArgumentNullException("interchangeContext");
     return ediSegment.StartsWith(EdiSegments.Una) ? EdiSegments.Una : ediSegment.Split(interchangeContext.DataElementSeparator.ToCharArray(), StringSplitOptions.None)[0];
 }
 /// <summary>
 /// Converts the interchange to edi message.
 /// </summary>
 /// <param name="context">
 /// The interchange context.
 /// This sets the non format default separators.
 /// </param>
 /// <returns>
 /// The edi message.
 /// </returns>
 public abstract List<string> ToEdi(InterchangeContext context = null);
        public static string[] GetRepetitions(string value, InterchangeContext interchangeContext)
        {
            if (!string.IsNullOrEmpty(interchangeContext.ReleaseIndicator))
                return value.EscapeSplit(interchangeContext.ReleaseIndicator[0],
                    interchangeContext.RepetitionSeparator[0], StringSplitOptions.None);

            return value.Split(interchangeContext.RepetitionSeparator.ToCharArray());
        }
Exemple #24
0
        /// <summary>
        /// Convert a parse tree to a root XML node.
        /// Without the hierarchy, only the name.
        /// </summary>
        /// <param name="parseTree">The parse tree.</param>
        /// <param name="interchangeContext">The interchange context.</param>
        /// <returns>A XML node.</returns>
        private static XElement ToXml(ParseTree parseTree, InterchangeContext interchangeContext)
        {
            XNamespace ns = interchangeContext.TargetNamespace;

            return(new XElement(ns + parseTree.Name));
        }
Exemple #25
0
 /// <summary>
 /// Initializes a new instance of the <see cref="InterchangeLexer"/> class.
 /// </summary>
 /// <param name="ediString">
 /// The edi message.
 /// </param>
 /// <param name="definitionsAssemblyName">The assembly name of the project containing the classes and xsd.</param>
 protected InterchangeLexer(string ediString, string definitionsAssemblyName)
 {
     _ediString = ediString;
     InterchangeContext = new InterchangeContext(ediString, definitionsAssemblyName);
 }
Exemple #26
0
        public void TestToEdiWithInvalidContext()
        {
            // ARRANGE
            const string sample = "EdiFabric.Tests.Xml.Edifact_INVOIC_D00A_EscapedSegmentTerminator.xml";
            var interchangeContext = new InterchangeContext
                                         {
                                             DataElementSeparator = "|",
                                             ComponentDataElementSeparator = "|"
                                         };

            // ACT
            try
            {
                Interchange.LoadFrom(
                        XElement.Load(Assembly.GetExecutingAssembly().GetManifestResourceStream(sample))).ToEdi(interchangeContext);
            }
            catch (Exception ex)
            {
                // ASSERT
                Assert.IsInstanceOfType(ex, typeof(ParserException));
                Assert.IsTrue(ex.Message.StartsWith("Invalid interchange context"));
            }
        }
Exemple #27
0
 /// <summary>
 /// Initializes a new instance of the <see cref="MessageContext"/> class.
 /// </summary>
 /// <param name="message">
 /// From xml
 /// </param>
 /// <param name="interchangeContext">
 /// The interchange context
 /// </param>
 public MessageContext(XElement message, InterchangeContext interchangeContext)
 {
     ToContext(message);
     _systemType = ToSystemType(Format, Version, Tag, Origin, interchangeContext.DefinitionsAssemblyName);
 }
        /// <summary>
        /// Converts edi interchange headers into message context.
        /// </summary>
        /// <param name="envelopes">The interchange headers.</param>
        /// <param name="interchangeContext">The interchange context.</param>
        /// <returns>
        /// The message context.
        /// </returns>
        private Tuple<string, string, string, EdiFormats> ToContextX12(IEnumerable<string> envelopes, InterchangeContext interchangeContext)
        {
            var enumerable = envelopes as List<string> ?? envelopes.ToList();
            string version;
            string origin;
            string format;
            string tag;

            try
            {
                var gs = enumerable.Single(es => es.StartsWith(EdiSegments.Gs));
                var ediCompositeDataElementsGs = EdiHelper.GetEdiCompositeDataElements(gs, interchangeContext);

                version = ediCompositeDataElementsGs[7].Substring(0, 6);
                origin = ediCompositeDataElementsGs[7].Count() >= 10
                    ? ediCompositeDataElementsGs[7].Substring(6, 4)
                    : null;
                format = HipaaHelper.IsHipaa(version + origin) ? EdiFormats.Hipaa.ToString() : EdiFormats.X12.ToString();

                if (!HipaaHelper.IsHipaa(version + origin))
                {
                    origin = null;
                }
            }
            catch(Exception ex)
            {
                throw new ParserException("Can't parse GS segment.", ex);
            }

            try
            {
                var st = enumerable.Single(es => es.StartsWith(EdiSegments.St));
                var ediCompositeDataElementsSt = EdiHelper.GetEdiCompositeDataElements(st, interchangeContext);
                tag = ediCompositeDataElementsSt[0];
            }
            catch (Exception ex)
            {
                throw new ParserException("Can't parse ST segment.", ex);
            }

            return new Tuple<string, string, string, EdiFormats>(tag, version, origin, ToFormat(format));
        }
        /// <summary>
        /// Converts edi interchange headers into message context.
        /// </summary>
        /// <param name="envelopes">The interchange headers.</param>
        /// <param name="interchangeContext">The interchange context.</param>
        /// <returns>
        /// The message context.
        /// </returns>
        private Tuple<string, string, string, EdiFormats> ToContextEdifact(IEnumerable<string> envelopes, InterchangeContext interchangeContext)
        {
            try
            {
                var unh = envelopes.Single(es => es.StartsWith(EdiSegments.Unh));
                var ediCompositeDataElements = EdiHelper.GetEdiCompositeDataElements(unh, interchangeContext);
                var ediDataElements = EdiHelper.GetEdiComponentDataElements(ediCompositeDataElements[1], interchangeContext);

                return new Tuple<string, string, string, EdiFormats>(ediDataElements[0], ediDataElements[1] + ediDataElements[2], null, EdiFormats.Edifact);
             }
            catch (Exception ex)
            {
                throw new ParserException("Can't parse UNH segment.", ex);
            }
        }
        /// <summary>
        /// Converts edi interchange headers into message context.
        /// </summary>
        /// <param name="envelopes">The interchange headers.</param>
        /// <param name="interchangeContext">The interchange context.</param>
        /// <returns>
        /// The message context.
        /// </returns>
        private Tuple<string, string, string, EdiFormats> ToContext(IEnumerable<string> envelopes, InterchangeContext interchangeContext)
        {
            if (envelopes == null) throw new ArgumentNullException("envelopes");

            switch (interchangeContext.Format)
            {
                case EdiFormats.Edifact:
                    return ToContextEdifact(envelopes, interchangeContext);
                case EdiFormats.X12:
                    return ToContextX12(envelopes, interchangeContext);
            }

            throw new Exception(string.Format("Unsupported message format = {0}", interchangeContext.Format));
        }
Exemple #31
0
        private static string CleanupTrailingSeparators(string result, string separator, InterchangeContext interchangeContext)
        {
            while (result.EndsWith(separator))
            {
                if (!string.IsNullOrEmpty(interchangeContext.ReleaseIndicator) && result.EndsWith(interchangeContext.ReleaseIndicator + separator))
                {
                    break;
                }

                result = result.Substring(0, result.Length - separator.Length);
            }

            return(result);
        }
Exemple #32
0
        /// <summary>
        /// Converts edi interchange headers into message context.
        /// </summary>
        /// <param name="envelopes">The interchange headers.</param>
        /// <param name="interchangeContext">The interchange context.</param>
        /// <returns>
        /// The message context.
        /// </returns>
        private Tuple <string, string, string, EdiFormats> ToContext(IEnumerable <string> envelopes, InterchangeContext interchangeContext)
        {
            if (envelopes == null)
            {
                throw new ArgumentNullException("envelopes");
            }

            switch (interchangeContext.Format)
            {
            case EdiFormats.Edifact:
                return(ToContextEdifact(envelopes, interchangeContext));

            case EdiFormats.X12:
                return(ToContextX12(envelopes, interchangeContext));
            }

            throw new Exception(string.Format("Unsupported message format = {0}", interchangeContext.Format));
        }
Exemple #33
0
        /// <summary>
        /// Lexical analysis of the message
        /// </summary>
        /// <param name="segments">The edi segments.</param>
        /// <param name="envelopes">The edi envelopes.</param>
        /// <param name="interchangeContext">The interchange context.</param>
        /// <returns>The pased edi message.</returns>
        public static Message Analyze(List <string> segments, List <string> envelopes, InterchangeContext interchangeContext)
        {
            // Read the message context from the envelope headers
            var messageContext = new MessageContext(envelopes, interchangeContext);

            // This will read through the grammar and will build an xml

            // Get the grammar from the context
            var messageGrammar = ParseTree.LoadFrom(messageContext.SystemType,
                                                    pt => pt.IsMessage || pt.IsGroup || pt.IsChoice || pt.IsAll || pt.IsLoopOfLoops);
            // Set the position in the grammar
            var lastSegment = messageGrammar.Children.First();

            // Create the xml root of the parsed edi
            var ediXml = ToXml(messageGrammar, interchangeContext);
            // Set the position in the xml
            var lastXElement = ediXml;

            // Iterate trough the segment lines
            foreach (var segment in segments)
            {
                try
                {
                    // Find the next segment grammar
                    var currSeg = lastSegment.FindNextSegment(new SegmentFullName(segment, interchangeContext, messageContext.Format));
                    // Build the segment hierarchy
                    // This will move to the required level up for the segment parents: groups, choices, all and loop of loops,
                    // until another group is reached.
                    var segmentTree = GetSegmentTree(currSeg, lastSegment);
                    // Intersect the grammar with the parsed xml.
                    // The new chunk will be attched to this intersection point.
                    lastXElement = lastXElement.AncestorsAndSelf().Last(xe => xe.Name.LocalName == segmentTree.First().Parent.Name);

                    // Attach each bit
                    foreach (var parseTree in segmentTree)
                    {
                        // Parse if a segment, otherwise convert to xml
                        var element = parseTree.IsSegment
                            ? SegmentParser.ParseLine(parseTree, segment, interchangeContext)
                            : ToXml(parseTree, interchangeContext);

                        // Attach to the xml
                        lastXElement.Add(element);
                        // Set the last attached as the attachment point as we iterate from the top parent to the bottom segment
                        lastXElement = element;
                    }

                    // Reset the position in the grammar
                    lastSegment = currSeg;
                }
                catch (Exception ex)
                {
                    throw new ParserException("Failed at line: " + segment, ex);
                }
            }

            return(new Message(ediXml, messageContext));
        }
Exemple #34
0
        public void TestToEdiWithSegmentList()
        {
            // ARRANGE
            const string sample = "EdiFabric.Tests.Xml.X12_810_00204_SegmentList.xml";
            const string expectedResult = "EdiFabric.Tests.Edi.X12_810_00204.txt";

            var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(expectedResult);
            Debug.Assert(stream != null, "stream != null");

            var reader = new StreamReader(stream);
            var expectedEdi = new List<string>();
            while (reader.Peek() >= 0)
            {
                expectedEdi.Add(reader.ReadLine());
            }
            var interchangeContext = new InterchangeContext
            {
                RepetitionSeparator = "|"
            };

            // ACT
            var parsedEdi =
                Interchange.LoadFrom(XElement.Load(Assembly.GetExecutingAssembly().GetManifestResourceStream(sample))).ToEdi(interchangeContext);

            // ASSERT
            Assert.AreEqual(expectedEdi.Count, parsedEdi.Count);
            for (int i = 0; i < parsedEdi.Count; i++)
            {
                Assert.IsTrue(parsedEdi[i] == expectedEdi[i]);
            }
        }
Exemple #35
0
        public void TestToEdiWithSegmentsComparisonAndNonDefaultSeparators()
        {
            // ARRANGE
            const string sample = "EdiFabric.Tests.Xml.Edifact_INVOIC_D00A.xml";
            const string expectedResult = "EdiFabric.Tests.Edi.Edifact_INVOIC_D00A_NonDefaultSeparators.txt";

            var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(expectedResult);
            Debug.Assert(stream != null, "stream != null");

            var reader = new StreamReader(stream);
            var expectedEdi = new List<string>();
            while (reader.Peek() >= 0)
            {
                expectedEdi.Add(reader.ReadLine());
            }

            // ACT
            var interchangeContext = new InterchangeContext { DataElementSeparator = "|", SegmentTerminator = "'"};
            var parsedEdi = Interchange.LoadFrom(XElement.Load(Assembly.GetExecutingAssembly().GetManifestResourceStream(sample))).ToEdi(interchangeContext);

            // ASSERT
            Assert.AreEqual(expectedEdi.Count, parsedEdi.Count);
            for (int i = 0; i < parsedEdi.Count; i++)
            {
                Assert.IsTrue(parsedEdi[i] == expectedEdi[i]);
            }
        }
 //-----------------------------------------------------------------------------------------------------
 public FileAnalysis Func_File_Validate(
     string filename,
     string errorOut,
     string validOut,
     string type,
     char dataSep,
     char lineSep)
 {
     this.FileStatus = new FileAnalysis();
     if (File.Exists(filename))
     {
         try
         {
             this.FileStatus.HasError = Func_File_Validate(filename);
             this.FileStatus.HasCWError = Func_File_Validate_StatusAndFilename(filename);
             if (this.FileStatus.HasError && (this.FileStatus.HasCWError == false))
             {
                 if (!filename.Contains(type))
                 {
                     var ediObject = Interchange.LoadFrom(File.OpenRead(filename));
                     if (ediObject.Groups != null)
                     {
                         foreach (var g in ediObject.Groups)
                         {
                             foreach (var m in g.Messages)
                             {
                                 var brokenRules = (List<string>) m.Validate();
                                 if (brokenRules.Count > 0)
                                 {
                                     this.FileStatus.HasError = true;
                                     this.FileStatus.Errors = Func_X12_AssignErrors(brokenRules);
                                     this.FileStatus.Fixable = Func_X12_Eval_ErrorCodes(
                                         this.FileStatus.Errors,
                                         type);
                                     this.FileStatus.HasCWError = Func_File_Validate_StatusAndFilename(filename);
                                     if (this.FileStatus.Fixable && (!filename.Contains(type))
                                         && (this.FileStatus.HasCWError == false))
                                     {
                                         var errContext = new InterchangeContext
                                         {
                                             DataElementSeparator =
                                                 dataSep.ToString(),
                                             SegmentTerminator =
                                                 lineSep.ToString()
                                         };
                                         var errContent = Func_X12_Eval_Segments(
                                             filename,
                                             ediObject.ToEdi(errContext),
                                             type,
                                             dataSep,
                                             lineSep);
                                         if (
                                             File.Exists(
                                                 string.Concat(
                                                     Path.GetDirectoryName(filename),
                                                     "\\",
                                                     Path.GetFileNameWithoutExtension(filename),
                                                     "_",
                                                     type,
                                                     ".txt")))
                                         {
                                             File.Delete(
                                                 string.Concat(
                                                     Path.GetDirectoryName(filename),
                                                     "\\",
                                                     Path.GetFileNameWithoutExtension(filename),
                                                     "_",
                                                     type,
                                                     ".txt"));
                                         }
                                         TextWriter errWriter =
                                             File.CreateText(
                                                 string.Concat(
                                                     Path.GetDirectoryName(filename),
                                                     "\\",
                                                     Path.GetFileNameWithoutExtension(filename),
                                                     "_",
                                                     type,
                                                     ".txt"));
                                         try
                                         {
                                             errWriter.Write(string.Concat(errContent));
                                         }
                                         finally
                                         {
                                             ((IDisposable) errWriter).Dispose();
                                         }
                                         this.FileStatus.HasError =
                                             Func_File_Validate(
                                                 string.Concat(
                                                     Path.GetDirectoryName(filename),
                                                     "\\",
                                                     Path.GetFileNameWithoutExtension(filename),
                                                     "_",
                                                     type,
                                                     ".txt"));
                                         if (this.FileStatus.HasError)
                                         {
                                             Func_File_Move(
                                                 filename,
                                                 string.Concat(errorOut, "\\", Path.GetFileName(filename)));
                                             this.FileStatus.FileErrName = string.Concat(
                                                 errorOut,
                                                 "\\",
                                                 Path.GetFileName(filename));
                                             this.FileStatus.ExcpMessage = "Cannot Recover From EDI Errors: "
                                                                           + filename;
                                             this.FileStatus.Status = false;
                                             if (
                                                 File.Exists(
                                                     string.Concat(
                                                         Path.GetDirectoryName(filename),
                                                         "\\",
                                                         Path.GetFileNameWithoutExtension(filename),
                                                         "_",
                                                         type,
                                                         ".txt")))
                                             {
                                                 File.Delete(
                                                     string.Concat(
                                                         Path.GetDirectoryName(filename),
                                                         "\\",
                                                         Path.GetFileNameWithoutExtension(filename),
                                                         "_",
                                                         type,
                                                         ".txt"));
                                             }
                                             return this.FileStatus;
                                         }
                                         this.FileStatus.FileOutName =
                                             string.Concat(
                                                 Path.GetDirectoryName(filename),
                                                 "\\",
                                                 Path.GetFileNameWithoutExtension(filename),
                                                 "_",
                                                 type,
                                                 ".txt");
                                         this.FileStatus.Status = true;
                                         this.FileStatus.Created = true;
                                         if (File.Exists(filename))
                                         {
                                             File.Delete(filename);
                                         }
                                         return this.FileStatus;
                                     }
                                     Func_File_Move(
                                         filename,
                                         string.Concat(errorOut, "\\", Path.GetFileName(filename)));
                                     this.FileStatus.FileErrName = string.Concat(
                                         errorOut,
                                         "\\",
                                         Path.GetFileName(filename));
                                     this.FileStatus.ExcpMessage = "Cannot Recover From EDI Errors: " + filename;
                                     this.FileStatus.Status = false;
                                     return this.FileStatus;
                                 }
                                 var valContext = new InterchangeContext
                                 {
                                     DataElementSeparator =
                                         dataSep.ToString(),
                                     SegmentTerminator =
                                         lineSep.ToString()
                                 };
                                 var valContent = Func_X12_Eval_Segments(
                                     filename,
                                     ediObject.ToEdi(valContext),
                                     type,
                                     dataSep,
                                     lineSep);
                                 if (Func_Data_ListIsEqual(valContent, ediObject.ToEdi(valContext)))
                                 {
                                     Func_File_Move(
                                         filename,
                                         string.Concat(validOut, "\\", Path.GetFileName(filename)));
                                     this.FileStatus.FileErrName = string.Concat(
                                         validOut,
                                         "\\",
                                         Path.GetFileName(filename));
                                     this.FileStatus.Created = true;
                                     this.FileStatus.Status = true;
                                     return this.FileStatus;
                                 }
                                 if (
                                     File.Exists(
                                         string.Concat(
                                             Path.GetDirectoryName(filename),
                                             "\\",
                                             Path.GetFileNameWithoutExtension(filename),
                                             "_",
                                             type,
                                             ".txt")))
                                 {
                                     File.Delete(
                                         string.Concat(
                                             Path.GetDirectoryName(filename),
                                             "\\",
                                             Path.GetFileNameWithoutExtension(filename),
                                             "_",
                                             type,
                                             ".txt"));
                                 }
                                 TextWriter valWriter =
                                     File.CreateText(
                                         string.Concat(
                                             Path.GetDirectoryName(filename),
                                             "\\",
                                             Path.GetFileNameWithoutExtension(filename),
                                             "_",
                                             type,
                                             ".txt"));
                                 try
                                 {
                                     valWriter.Write(string.Concat(valContent));
                                 }
                                 finally
                                 {
                                     ((IDisposable) valWriter).Dispose();
                                 }
                                 Func_File_Move(
                                     filename,
                                     string.Concat(validOut, "\\", Path.GetFileName(filename)));
                                 this.FileStatus.FileErrName = string.Concat(
                                     validOut,
                                     "\\",
                                     Path.GetFileName(filename));
                                 this.FileStatus.Created = true;
                                 this.FileStatus.Status = true;
                                 return this.FileStatus;
                             }
                         }
                     }
                 }
                 else
                 {
                     Func_File_Move(filename, string.Concat(errorOut, "\\", Path.GetFileName(filename)));
                     this.FileStatus.FileErrName = string.Concat(errorOut, "\\", Path.GetFileName(filename));
                     this.FileStatus.ExcpMessage = "Cannot Recover From EDI Errors";
                     this.FileStatus.Status = false;
                     this.FileStatus.Created = false;
                     return this.FileStatus;
                 }
             }
             else
             {
                 if (this.FileStatus.HasCWError)
                 {
                     Func_File_Move(filename, string.Concat(errorOut, "\\", Path.GetFileName(filename)));
                     this.FileStatus.FileErrName = string.Concat(errorOut, "\\", Path.GetFileName(filename));
                     this.FileStatus.Status = false;
                     this.FileStatus.Created = false;
                     return this.FileStatus;
                 }
                 Func_File_Move(filename, string.Concat(validOut, "\\", Path.GetFileName(filename)));
                 this.FileStatus.FileErrName = string.Concat(validOut, "\\", Path.GetFileName(filename));
                 this.FileStatus.Created = true;
                 this.FileStatus.Status = true;
                 return this.FileStatus;
             }
         }
         catch (ParserException parEx)
         {
             Func_File_Move(filename, string.Concat(errorOut, "\\", Path.GetFileName(filename)));
             this.FileStatus.FileErrName = string.Concat(errorOut, "\\", Path.GetFileName(filename));
             this.FileStatus.ExcpMessage = parEx.Message;
             this.FileStatus.Status = false;
             this.FileStatus.Created = false;
             return this.FileStatus;
         }
         catch (NullReferenceException nulEx)
         {
             Func_File_Move(filename, string.Concat(errorOut, "\\", Path.GetFileName(filename)));
             this.FileStatus.FileErrName = string.Concat(errorOut, "\\", Path.GetFileName(filename));
             this.FileStatus.ExcpMessage = nulEx.Message;
             this.FileStatus.Status = false;
             this.FileStatus.Created = false;
             return this.FileStatus;
         }
     }
     else
     {
         this.FileStatus.ExcpMessage = "Could Not Find: " + filename;
         this.FileStatus.Status = false;
         this.FileStatus.Created = false;
         return this.FileStatus;
     }
     return this.FileStatus;
 }
Exemple #37
0
        /// <summary>
        /// Converts edi interchange headers into message context.
        /// </summary>
        /// <param name="envelopes">The interchange headers.</param>
        /// <param name="interchangeContext">The interchange context.</param>
        /// <returns>
        /// The message context.
        /// </returns>
        private Tuple <string, string, string, EdiFormats> ToContextEdifact(IEnumerable <string> envelopes, InterchangeContext interchangeContext)
        {
            try
            {
                var unh = envelopes.Single(es => es.StartsWith(EdiSegments.Unh));
                var ediCompositeDataElements = EdiHelper.GetEdiCompositeDataElements(unh, interchangeContext);
                var ediDataElements          = EdiHelper.GetEdiComponentDataElements(ediCompositeDataElements[1], interchangeContext);

                return(new Tuple <string, string, string, EdiFormats>(ediDataElements[0], ediDataElements[1] + ediDataElements[2], null, EdiFormats.Edifact));
            }
            catch (Exception ex)
            {
                throw new ParserException("Can't parse UNH segment.", ex);
            }
        }
Exemple #38
0
        /// <summary>
        /// Lexical analysis of the message
        /// </summary>
        /// <param name="segments">The edi segments.</param>
        /// <param name="envelopes">The edi envelopes.</param>
        /// <param name="interchangeContext">The interchange context.</param>
        /// <returns>The passed Edi message.</returns>
        public static Message Analyze(List<string> segments, List<string> envelopes, InterchangeContext interchangeContext)
        {
            // Read the message context from the envelope headers
            var messageContext = new MessageContext(envelopes, interchangeContext);

            // This will read through the grammar and will build an xml

            // Get the grammar from the context
            var messageGrammar = ParseTree.LoadFrom(messageContext.SystemType,
                pt => pt.IsMessage || pt.IsGroup || pt.IsChoice || pt.IsAll || pt.IsLoopOfLoops);
            // Set the position in the grammar
            var lastSegment = messageGrammar.Children.First();

            // Create the xml root of the parsed edi
            var ediXml = ToXml(messageGrammar, interchangeContext);
            // Set the position in the xml
            var lastXElement = ediXml;

            // Iterate trough the segment lines
            foreach (var segment in segments)
            {
                try
                {
                    var segmentContext = new SegmentContext(segment, interchangeContext, messageContext.Format);

                    Logger.Log(string.Format("Segment to find: {0}", segmentContext.ToPropertiesString()));

                    // Jump back to HL segment if needed
                    if (segmentContext.IsJump())
                    {
                        XElement hlParent;
                        if (segmentContext.ParentId != null)
                        {
                            // Parent HL, start right after it
                            hlParent = ediXml.Descendants().Single(d => d.Name.LocalName.StartsWith("S_HL") &&
                                                                      d.Elements().First().Value == segmentContext.ParentId);
                            var hl = messageGrammar.Descendants().Single(pt => pt.Name == hlParent.Name.LocalName);
                            lastSegment = hl.Parent.Children[1];
                        }
                        else
                        {
                            // Root HL, start from it
                            hlParent = ediXml.Descendants().First(d => d.Name.LocalName.StartsWith("S_HL"));
                            var hl = messageGrammar.Descendants().Single(pt => pt.Name == hlParent.Name.LocalName);
                            lastSegment = hl;
                        }
                    }

                    // Find the next segment grammar
                    var currSeg = lastSegment.FindNextSegment(segmentContext);

                    Logger.Log(string.Format("Segment found: {0}", currSeg.Name));

                    // Build the segment hierarchy
                    // This will move to the required level up for the segment parents: groups, choices, all and loop of loops,
                    // until another group is reached.
                    var segmentTree = GetSegmentTree(currSeg, lastSegment);
                    // Intersect the grammar with the parsed XML.
                    // The new chunk will be attached to this intersection point.
                    lastXElement = lastXElement.AncestorsAndSelf().Last(xe => xe.Name.LocalName == segmentTree.First().Parent.Name);

                    // Attach each bit
                    foreach (var parseTree in segmentTree)
                    {
                        // Parse if a segment, otherwise convert to XML
                        var element = parseTree.IsSegment
                            ? SegmentParser.ParseLine(parseTree, segment, interchangeContext)
                            : ToXml(parseTree, interchangeContext);

                        // Attach to the XML
                        lastXElement.Add(element);
                        // Set the last attached as the attachment point as we iterate from the top parent to the bottom segment
                        lastXElement = element;
                    }

                    // Reset the position in the grammar
                    lastSegment = currSeg;
                    //var lastfound = AttachTree(segmentTree, segment, interchangeContext);

                }
                catch (Exception ex)
                {
                    throw new ParserException("Failed at line: " + segment, ex);
                }
            }

            return new Message(ediXml, messageContext);
        }
Exemple #39
0
        /// <summary>
        /// Lexically analyses a message.
        /// </summary>
        /// <param name="segments">The EDI segments.</param>
        /// <param name="envelopes">The EDI envelopes.</param>
        /// <param name="interchangeContext">The interchange context.</param>
        /// <returns>The passed Edi message.</returns>
        public static Message Analyze(List <string> segments, List <string> envelopes, InterchangeContext interchangeContext)
        {
            // Read the message context from the envelope headers
            var messageContext = new MessageContext(envelopes, interchangeContext);

            // This will read through the grammar and will build an XML

            // Get the grammar from the context
            var messageGrammar = ParseTree.LoadFrom(messageContext.SystemType,
                                                    pt => pt.IsMessage || pt.IsGroup || pt.IsChoice || pt.IsAll || pt.IsLoopOfLoops);
            // Set the position in the grammar
            var lastSegment = messageGrammar.Children.First();

            // Create the XML root of the parsed EDI
            var ediXml = ToXml(messageGrammar, interchangeContext);
            // Set the position in the XML
            var lastXElement = ediXml;

            // Iterate trough the segment lines
            foreach (var segment in segments)
            {
                try
                {
                    var segmentContext = new SegmentContext(segment, interchangeContext, messageContext.Format);

                    Logger.Log(string.Format("Segment to find: {0}", segmentContext.ToPropertiesString()));

                    // Jump back to HL segment if needed
                    if (segmentContext.IsJump())
                    {
                        XElement hlParent;
                        if (segmentContext.ParentId != null)
                        {
                            // Parent HL, start right after it
                            hlParent = ediXml.Descendants().Single(d => d.Name.LocalName.StartsWith("S_HL") &&
                                                                   d.Elements().First().Value ==
                                                                   segmentContext.ParentId);
                            var hl = messageGrammar.Descendants().Single(pt => pt.Name == hlParent.Name.LocalName);
                            lastSegment = hl.Parent.Children[1];
                        }
                        else
                        {
                            // Root HL, start from it
                            hlParent = ediXml.Descendants().First(d => d.Name.LocalName.StartsWith("S_HL"));
                            var hl = messageGrammar.Descendants().Single(pt => pt.Name == hlParent.Name.LocalName);
                            lastSegment = hl;
                        }
                    }

                    // Find the next segment grammar
                    var currSeg = lastSegment.FindNextSegment(segmentContext);

                    Logger.Log(string.Format("Segment found: {0}", currSeg.Name));

                    // Build the segment hierarchy
                    // This will move to the required level up for the segment parents: groups, choices, all and loop of loops,
                    // until another group is reached.
                    var segmentTree = GetSegmentTree(currSeg, lastSegment);
                    // Intersect the grammar with the parsed XML.
                    // The new chunk will be attached to this intersection point.
                    lastXElement =
                        lastXElement.AncestorsAndSelf().Last(xe => xe.Name.LocalName == segmentTree.First().Parent.Name);

                    // Attach each bit
                    foreach (var parseTree in segmentTree)
                    {
                        // Parse if a segment, otherwise convert to XML
                        var element = parseTree.IsSegment
                            ? SegmentParser.ParseLine(parseTree, segment, interchangeContext)
                            : ToXml(parseTree, interchangeContext);

                        // Attach to the XML
                        lastXElement.Add(element);
                        // Set the last attached as the attachment point as we iterate from the top parent to the bottom segment
                        lastXElement = element;
                    }

                    // Reset the position in the grammar
                    lastSegment = currSeg;
                }
                catch (Exception ex)
                {
                    throw new ParserException("Failed at line: " + segment, ex);
                }
            }

            return(new Message(ediXml, messageContext));
        }
Exemple #40
0
        /// <summary>
        /// Parses a data element
        /// </summary>
        /// <param name="parseTree">The dataelement grammar.</param>
        /// <param name="value">The dataelement line.</param>
        /// <param name="interchangeContext"></param>
        /// <returns>The parsed xml.</returns>
        private static XElement ParseElement(ParseTree parseTree, string value, InterchangeContext interchangeContext)
        {
            if (value == null)
            {
                throw new ArgumentNullException("value");
            }
            if (!parseTree.IsComplex && !parseTree.IsSimple)
            {
                throw new Exception("Not a data element.");
            }

            XNamespace ns     = interchangeContext.TargetNamespace;
            var        result = new XElement(ns + parseTree.Name);

            if (parseTree.IsComplex)
            {
                if (value == string.Empty)
                {
                    // Only deal with blank values for envelope headers
                    if (parseTree.IsEnvelope)
                    {
                        foreach (var dataElement in parseTree.Children)
                        {
                            var element = new XElement(ns + dataElement.Name);
                            element.SetValue(string.Empty);
                            result.Add(element);
                        }
                    }
                }
                else
                {
                    // Get the simple data elements
                    var componentDataElements =
                        EdiHelper.GetEdiComponentDataElements(value, interchangeContext).ToList();

                    // Index the composite data elements from the class definition
                    var indexedGrammar =
                        parseTree.Children.Select((g, p) => new { Grammar = g, Position = p }).ToList();
                    // Index the composite data elements from the edi string
                    var indexedValues = componentDataElements.Select((v, p) => new { Value = v, Position = p }).ToList();

                    // This will try to parse the edi string into the class definition
                    // Load a parse tree against each value
                    // If there are more values in the edi string than in the class definition - they will be ignored
                    // If there are less values in the edi string than in the class definition - it will throw an exception
                    var indexedList = from ig in indexedGrammar
                                      from iv in indexedValues
                                      where ig.Position == iv.Position
                                      select new { ig.Position, iv.Value };

                    // Index the list so we can position each element
                    //var indexed = componentDataElements.Select((a, i) => new {Item = a, Position = i}).ToList();

                    foreach (var dataElement in indexedList)
                    {
                        // Skip blank data elements otherwise this will produce blank XML nodes
                        if (string.IsNullOrEmpty(dataElement.Value))
                        {
                            if (!parseTree.IsEnvelope)
                            {
                                continue;
                            }
                        }

                        // Handle the repetitions
                        // If the children the the edi straing are more than the class definition,
                        // Then the diff are considered repetitions of the last child in the class definition
                        var objectToParse = dataElement.Position >= parseTree.Children.Count
                                                ? parseTree.Children.Last()
                                                : parseTree.Children[dataElement.Position];

                        var element = new XElement(ns + objectToParse.Name);
                        // Set the value and escape to prevent faulty XML
                        element.SetValue(SecurityElement.Escape(dataElement.Value) ?? string.Empty);
                        result.Add(element);
                    }
                }
            }
            else
            {
                // Prevent faulty XML
                result.SetValue(SecurityElement.Escape(value) ?? string.Empty);
            }

            return(result);
        }
Exemple #41
0
 /// <summary>
 /// Initializes a new instance of the <see cref="MessageContext"/> class.
 /// </summary>
 /// <param name="envelopes">
 /// From interchange headers.
 /// </param>
 /// <param name="interchangeContext">
 /// The interchange context.
 /// </param>
 public MessageContext(IEnumerable <string> envelopes, InterchangeContext interchangeContext)
 {
     ToContext(envelopes, interchangeContext);
     _systemType = ToSystemType(Format, Version, Tag, Origin, interchangeContext.DefinitionsAssemblyName);
 }
Exemple #42
0
        /// <summary>
        /// Converts edi interchange headers into message context.
        /// </summary>
        /// <param name="envelopes">The interchange headers.</param>
        /// <param name="interchangeContext">The interchange context.</param>
        private void ToContextEdifact(IEnumerable<string> envelopes, InterchangeContext interchangeContext)
        {
            try
            {
                var unh = envelopes.Single(es => es.StartsWith(EdiSegments.Unh));
                var ediCompositeDataElements = EdiHelper.GetEdiCompositeDataElements(unh, interchangeContext);
                var ediDataElements = EdiHelper.GetEdiComponentDataElements(ediCompositeDataElements[1],
                    interchangeContext);

                Tag = ediDataElements[0];
                Version = ediDataElements[1] + ediDataElements[2];
                Origin = null;
                Format = EdiFormats.Edifact;
            }
            catch (Exception ex)
            {
                throw new ParserException("Can't parse UNH segment.", ex);
            }
        }
Exemple #43
0
 /// <summary>
 /// Convert a parse tree to a root xml node
 /// Without the hierarchy, only the name.
 /// </summary>
 /// <param name="parseTree">The parse tree.</param>
 /// <param name="interchangeContext">The interchange context.</param>
 /// <returns>A xml node.</returns>
 private static XElement ToXml(ParseTree parseTree, InterchangeContext interchangeContext)
 {
     XNamespace ns = interchangeContext.TargetNamespace;
     return new XElement(ns + parseTree.Name);
 }
Exemple #44
0
 /// <summary>
 /// Initializes a new instance of the <see cref="MessageContext"/> class.
 /// </summary>
 /// <param name="envelopes">
 /// From interchange headers
 /// </param>
 /// <param name="interchangeContext">
 /// The interchange context
 /// </param>
 public MessageContext(IEnumerable<string> envelopes, InterchangeContext interchangeContext)
 {
     ToContext(envelopes, interchangeContext);
     _systemType = ToSystemType(Format, Version, Tag, Origin, interchangeContext.DefinitionsAssemblyName);
 }
Exemple #45
0
 /// <summary>
 /// Initializes a new instance of the <see cref="MessageContext"/> class.
 /// </summary>
 /// <param name="message">
 /// From XML.
 /// </param>
 /// <param name="interchangeContext">
 /// The interchange context.
 /// </param>
 public MessageContext(XElement message, InterchangeContext interchangeContext)
 {
     ToContext(message);
     _systemType = ToSystemType(Format, Version, Tag, Origin, interchangeContext.DefinitionsAssemblyName);
 }
        /// <summary>
        /// Converts the interchange to edi message.
        /// </summary>
        /// <param name="context">
        /// The interchange context.
        /// This sets the non format default separators.
        /// </param>
        /// <returns>
        /// The edi message.
        /// </returns>
        public List<string> ToEdi(InterchangeContext context = null)
        {
            var x12Lexer = new ToEdiLexer(EdiHelper.Serialize(this), context);
            x12Lexer.Analyze();

            return x12Lexer.Result;
        }
Exemple #47
0
        /// <summary>
        /// Converts the interchange to edi message.
        /// </summary>
        /// <param name="context">
        /// The interchange context.
        /// This sets the non format default separators.
        /// </param>
        /// <returns>
        /// The edi message.
        /// </returns>
        public override List<string> ToEdi(InterchangeContext context = null)
        {
            var edifactLexer = new ToEdiLexer(EdiHelper.Serialize(this), context);
            edifactLexer.Analyze();

            return edifactLexer.Result;
        }
 //-----------------------------------------------------------------------------------------------------
 public List<string> Func_EDI_GetOriginalMessage(string filename, char dataSep, char lineSep)
 {
     var ediObject = Interchange.LoadFrom(File.OpenRead(filename));
     var ediContext = new InterchangeContext
     {
         DataElementSeparator = dataSep.ToString(),
         SegmentTerminator = lineSep.ToString()
     };
     var lstMsg = ediObject.ToEdi(ediContext);
     return lstMsg;
 }