Esempio n. 1
0
 /// <summary>
 /// Creates a <see cref="SegmentError"/> object with the segment metadata provided
 /// </summary>
 /// <param name="segmentInfo">Segment metadata object</param>
 /// <param name="syntaxErrorCode">Error code detailing syntax issue</param>
 /// <returns>Error object created with the metadata</returns>
 protected SegmentError CreateSegmentError(SegmentInformation segmentInfo, string syntaxErrorCode)
 {
     return(new SegmentError
     {
         SegmentIdCode = segmentInfo.SegmentId,
         SegmentPosition = segmentInfo.SegmentPosition,
         LoopIdentifierCode = segmentInfo.LoopId,
         ImplementationSegmentSyntaxErrorCode = syntaxErrorCode
     });
 }
Esempio n. 2
0
        /// <summary>
        /// Attempts to parse a segment and validates it againsts its specification. A collection of <see cref="SegmentError"/> objects is returned
        /// </summary>
        /// <param name="segmentInfo">Segment metadata to be validated</param>
        /// <returns>Collection of Segment errors, if found</returns>
        protected virtual IList <SegmentError> ValidateSegmentAgainstSpec(SegmentInformation segmentInfo)
        {
            var errors = new List <SegmentError>();

            if (segmentInfo.Spec != null)
            {
                for (int iSpec = 0; iSpec < segmentInfo.Spec.Elements.Count; iSpec++)
                {
                    var elementSpec = segmentInfo.Spec.Elements[iSpec];

                    if (iSpec < segmentInfo.Elements.Length - 1)
                    {
                        string element = segmentInfo.Elements[iSpec + 1];

                        if (string.IsNullOrEmpty(element) && elementSpec.Required)
                        {
                            errors.Add(this.CreateDataElementError(segmentInfo, iSpec + 1, "1", null));
                        }
                        else if (element.Length < elementSpec.MinLength && (elementSpec.Required || element.Length > 0))
                        {
                            errors.Add(this.CreateDataElementError(segmentInfo, iSpec + 1, "4", element));
                        }
                        else if (element.Length > elementSpec.MaxLength && elementSpec.MaxLength > 0)
                        {
                            errors.Add(this.CreateDataElementError(segmentInfo, iSpec + 1, "5", element));
                        }
                    }
                    else
                    {
                        if (elementSpec.Required)
                        {
                            errors.Add(this.CreateDataElementError(segmentInfo, iSpec + 1, "1", null));
                        }
                    }
                }

                if (segmentInfo.Elements.Length - 1 > segmentInfo.Spec.Elements.Count)
                {
                    int elementPosition = segmentInfo.Spec.Elements.Count + 1;
                    errors.Add(this.CreateDataElementError(segmentInfo, elementPosition, "3", segmentInfo.Elements[elementPosition]));
                }
            }

            return(errors);
        }
Esempio n. 3
0
        /// <summary>
        /// Creates a <see cref="SegmentError"/> object with the segment metadata provided
        /// </summary>
        /// <param name="segmentInfo">Segment metadata object</param>
        /// <param name="elementPositionInSegment">Element index position in segment</param>
        /// <param name="syntaxErrorCode">Error code detailing syntax issue</param>
        /// <param name="element">Element data</param>
        /// <returns>Error object created with the metadata</returns>
        protected SegmentError CreateDataElementError(SegmentInformation segmentInfo, int elementPositionInSegment, string syntaxErrorCode, string element)
        {
            var error = new SegmentError
            {
                SegmentIdCode      = segmentInfo.SegmentId,
                SegmentPosition    = segmentInfo.SegmentPosition,
                LoopIdentifierCode = segmentInfo.LoopId,
                ImplementationSegmentSyntaxErrorCode = "8"
            };

            error.ElementNotes.Add(new DataElementNote
            {
                PositionInSegment = new PositionInSegment {
                    ElementPositionInSegment = elementPositionInSegment
                },
                SyntaxErrorCode  = syntaxErrorCode,
                CopyOfBadElement = element
            });
            return(error);
        }
Esempio n. 4
0
        /// <summary>
        /// Builds a <see cref="TransactionSetResponse"/> object from the provided stream
        /// </summary>
        /// <param name="reader">Stream to pull transaction set data from</param>
        /// <param name="functionalCode">Function group code to associate with transaction set</param>
        /// <param name="versionIdentifierCode">Specification version code</param>
        /// <param name="transaction">Transaction segment string to be parsed</param>
        /// <returns>Transaction set response whether the set is valid, and the segment data</returns>
        protected virtual TransactionSetResponse AcknowledgeTransaction(X12StreamReader reader, string functionalCode, string versionIdentifierCode, string transaction)
        {
            string[] transactionElements = reader.SplitSegment(transaction);
            var      response            = new TransactionSetResponse
            {
                TransactionSetIdentifierCode = transactionElements[1],
                TransactionSetControlNumber  = transactionElements[2]
            };

            if (transactionElements.Length >= 4)
            {
                response.ImplementationConventionReference = transactionElements[3];
            }

            TransactionSpecification transactionSpec = this.specFinder.FindTransactionSpec(
                functionalCode,
                versionIdentifierCode,
                response.TransactionSetIdentifierCode);

            if (transactionSpec == null)
            {
                response.SyntaxErrorCodes.Add("1");
                response.AcknowledgmentCode = AcknowledgmentCode.R_Rejected;
                return(response);
            }

            var containers           = new Stack <ContainerInformation>();
            var transactionContainer = new ContainerInformation {
                Spec = transactionSpec
            };

            containers.Push(transactionContainer);
            var segmentInfos = new List <SegmentInformation>();

            string[] segments = transaction.Split(new[] { reader.Delimiters.SegmentTerminator }, System.StringSplitOptions.RemoveEmptyEntries);
            for (int i = 0; i < segments.Length; i++)
            {
                string[] elements    = segments[i].Split(reader.Delimiters.ElementSeparator);
                var      segmentInfo = new SegmentInformation {
                    SegmentId = elements[0], SegmentPosition = i + 1, Elements = elements
                };
                segmentInfo.Spec = this.specFinder.FindSegmentSpec(versionIdentifierCode, segmentInfo.SegmentId);
                segmentInfos.Add(segmentInfo);

                ContainerInformation currentContainer = containers.Peek();

                switch (segmentInfo.SegmentId)
                {
                case "ST":
                case "SE":
                    segmentInfo.LoopId = string.Empty;
                    transactionContainer.Segments.Add(segmentInfo);
                    break;

                case "HL":
                    string hloopNumber       = segmentInfo.Elements[1];
                    string hloopParentNumber = segmentInfo.Elements[2];
                    string hloopLevelCode    = segmentInfo.Elements[3];
                    HierarchicalLoopSpecification hloopSpec = transactionSpec.HierarchicalLoopSpecifications.FirstOrDefault(hls => hls.LevelCode == hloopLevelCode);
                    if (hloopSpec != null)
                    {
                        while (!(containers.Peek().Spec is TransactionSpecification))
                        {
                            if (containers.Peek().HLoopNumber == hloopParentNumber)
                            {
                                break;
                            }

                            containers.Pop();
                        }

                        segmentInfo.LoopId = hloopSpec.LoopId;
                        var hloopContainer = new ContainerInformation {
                            Spec = hloopSpec, HLoopNumber = hloopNumber
                        };
                        hloopContainer.Segments.Add(segmentInfo);
                        containers.Peek().Containers.Add(hloopContainer);
                        containers.Push(hloopContainer);
                    }
                    else
                    {
                        response.SegmentErrors.Add(this.CreateDataElementError(segmentInfo, 3, "I6", hloopLevelCode));
                        response.AcknowledgmentCode = AcknowledgmentCode.X_Rejected_ContentCouldNotBeAnalyzed;
                    }

                    break;

                default:
                    bool matchFound = false;
                    do
                    {
                        var matchingLoopSpecs = currentContainer.Spec.LoopSpecifications.Where(ls => ls.StartingSegment.SegmentId == segmentInfo.SegmentId).ToList();

                        if (matchingLoopSpecs.Count > 0)
                        {
                            IContainerSpecification matchingLoopSpec;
                            if (matchingLoopSpecs.Count == 1)
                            {
                                matchingLoopSpec = matchingLoopSpecs.First();
                            }
                            else
                            {
                                string entityCode = elements[1];
                                matchingLoopSpec = matchingLoopSpecs.FirstOrDefault(ls => ls.StartingSegment.EntityIdentifiers.Exists(ei => ei.Code == entityCode));
                            }

                            if (matchingLoopSpec != null)
                            {
                                segmentInfo.LoopId = matchingLoopSpec.LoopId;
                                var loopContainer = new ContainerInformation {
                                    Spec = matchingLoopSpec
                                };
                                loopContainer.Segments.Add(segmentInfo);
                                containers.Peek().Containers.Add(loopContainer);
                                containers.Push(loopContainer);
                                matchFound = true;
                            }
                            else
                            {
                                response.SegmentErrors.Add(this.CreateSegmentError(segmentInfo, "6"));
                                response.AcknowledgmentCode = AcknowledgmentCode.X_Rejected_ContentCouldNotBeAnalyzed;
                                return(response);
                            }
                        }
                        else if (currentContainer.Spec.SegmentSpecifications.Exists(ss => ss.SegmentId == segmentInfo.SegmentId))
                        {
                            segmentInfo.LoopId = currentContainer.Spec.LoopId;
                            currentContainer.Segments.Add(segmentInfo);
                            matchFound = true;
                        }
                        else
                        {
                            if (currentContainer.Spec is TransactionSpecification)
                            {
                                response.SegmentErrors.Add(this.CreateSegmentError(segmentInfo, "2"));
                                response.AcknowledgmentCode = AcknowledgmentCode.X_Rejected_ContentCouldNotBeAnalyzed;
                                return(response);
                            }

                            containers.Pop();
                            currentContainer = containers.Peek();
                        }
                    }while (!matchFound);

                    break;
                }

                response.SegmentErrors.AddRange(this.ValidateSegmentAgainstSpec(segmentInfo));
            }

            response.SegmentErrors.AddRange(this.ValidateContainerAgainstSpec(transactionContainer));

            var trailerSegment = segmentInfos.FirstOrDefault(si => si.SegmentId == "SE");

            if (trailerSegment == null)
            {
                response.SyntaxErrorCodes.Add("2");
            }
            else
            {
                if (trailerSegment.Elements.Length <= 2 || trailerSegment.Elements[2] != response.TransactionSetControlNumber)
                {
                    response.SyntaxErrorCodes.Add("3");
                }

                if (trailerSegment.Elements.Length >= 2)
                {
                    int segmentCount;
                    int.TryParse(trailerSegment.Elements[1], out segmentCount);
                    if (segmentCount != segmentInfos.Count)
                    {
                        response.SyntaxErrorCodes.Add("4");
                    }
                }
                else
                {
                    response.SyntaxErrorCodes.Add("4");
                }
            }

            if (response.SegmentErrors.Count > 0 || response.SyntaxErrorCodes.Count > 0)
            {
                if (response.SegmentErrors.Count > 0)
                {
                    response.SyntaxErrorCodes.Add("5");
                }

                if (response.AcknowledgmentCode == AcknowledgmentCode.A_Accepted)
                {
                    response.AcknowledgmentCode = AcknowledgmentCode.E_Accepted_ButErrorsWereNoted;
                }
            }

            return(response);
        }