예제 #1
0
        /// <summary>
        /// Parses a segment
        /// </summary>
        /// <param name="line">The segment line.</param>
        /// <param name="grammar">The segment grammar.</param>
        /// <param name="interchangeContext">The interchange context.</param>
        /// <returns>The parsed xml.</returns>
        private static XElement Parse(ParseTree grammar, string line, InterchangeContext interchangeContext)
        {
            if (!grammar.IsSegment)
            {
                throw new Exception("Not a segment.");
            }

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

            // Gets the composite data elements from the segment string
            var dataElements = EdiHelper.GetEdiCompositeDataElements(line, interchangeContext).ToList();

            // Index the composite data elements from the class definition
            var indexedGrammar = grammar.Children.Select((g, p) => new { Grammar = g, Position = p }).ToList();
            // Index the composite data elements from the edi string
            var indexedValues = dataElements.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.Grammar, iv.Value, ig.Position };

            foreach (var dataElement in indexedList)
            {
                // Skip the blank elements
                // This massively reduces the generated XML
                if (string.IsNullOrEmpty(dataElement.Value))
                {
                    // Don't skip for header segments as they are positional
                    if (!grammar.IsEnvelope)
                    {
                        continue;
                    }
                }

                // If the current element is out of the range of elemnts defined in the definition class, then it's a repetition
                // The repetitions are always for the last defined element
                var elementGrammar = dataElement.Position >= grammar.Children.Count
                    ? grammar.Children.Last()
                    : grammar.Children[dataElement.Position];

                // Handle the repetitions
                var elementRepetitions = grammar.IsEnvelope
                    ? new[] { dataElement.Value }
                    : EdiHelper.GetRepetitions(dataElement.Value, interchangeContext);

                // Parse each repetition
                foreach (var elementRepetition in elementRepetitions)
                {
                    result.Add(ParseElement(elementGrammar, elementRepetition, interchangeContext));
                }
            }

            return(result);
        }
예제 #2
0
        /// <summary>
        /// Lexical analysis of the segments
        /// </summary>
        public void Analyze()
        {
            var message  = new List <string>();
            var envelope = new List <string>();

            // Loads all messages in memory
            foreach (var segment in EdiHelper.GetEdiSegments(_ediString, InterchangeContext))
            {
                switch (EdiHelper.GetSegmentName(segment, InterchangeContext))
                {
                case EdiSegments.Una:
                    break;

                case EdiSegments.Unb:
                case EdiSegments.Isa:
                    CreateInterchangeHeader(segment);
                    break;

                case EdiSegments.Unz:
                case EdiSegments.Iea:
                    CreateInterchangeTrailer(segment);
                    break;

                case EdiSegments.Ung:
                    CreateGroupHeader(segment);
                    break;

                case EdiSegments.Gs:
                    CreateGroupHeader(segment);
                    envelope.Add(segment);
                    break;

                case EdiSegments.Une:
                case EdiSegments.Ge:
                    CreateGroupTrailer(segment);
                    envelope.Clear();
                    break;

                case EdiSegments.Unh:
                case EdiSegments.St:
                    message.Add(segment);
                    envelope.Add(segment);
                    break;

                case EdiSegments.Unt:
                case EdiSegments.Se:
                    message.Add(segment);
                    CreateMessage(message, envelope);
                    // For X12 the ST segment is included in the headers
                    // Once the message is parsed - it's removed
                    envelope.Remove(envelope.Last());
                    message.Clear();
                    break;

                default:
                    message.Add(segment);
                    break;
                }
            }
        }
예제 #3
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 List <string> ToEdi(InterchangeContext context = null)
        {
            var edifactLexer = new ToEdiLexer(EdiHelper.Serialize(this), context);

            edifactLexer.Analyze();

            return(edifactLexer.Result);
        }
예제 #4
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 x12Lexer = new ToEdiLexer(EdiHelper.Serialize(this), context);

            x12Lexer.Analyze();

            return(x12Lexer.Result);
        }
예제 #5
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);
            }
        }
예제 #6
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);
        }
예제 #7
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);
            }
        }
예제 #8
0
 /// <summary>
 /// Serialize the interchange into xml
 /// </summary>
 /// <returns>
 /// The serialized xml.
 /// </returns>
 public XElement Serialize()
 {
     return(EdiHelper.Serialize(this));
 }
예제 #9
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);
        }
예제 #10
0
 /// <summary>
 /// Initializes a new instance of the <see cref="Message"/> class.
 /// </summary>
 /// <param name="instance">
 /// Edi object.
 /// </param>
 /// <example>
 /// Set UNT segments count.
 /// <code lang="C#">
 /// var mInvoic = new M_INVOIC();
 /// // ... build the message
 ///
 /// var msg = new Message(mInvoic);
 /// var segCount = msg.Item.Descendants().Count(d => d.Name.LocalName.StartsWith("S_"));
 ///
 /// var nmn = new XmlNamespaceManager(new NameTable());
 /// nmn.AddNamespace("p", "www.edifabric.com/edifact");
 ///
 /// var untSegCount = msg.Item.XPathSelectElement("./p:S_UNT/p:D_0074_1", nmn);
 /// untSegCount.SetValue(segCount);
 /// </code>
 /// </example>
 public Message(object instance)
 {
     Context = new MessageContext(instance.GetType());
     Item    = EdiHelper.Serialize(instance);
 }