public SqlTransactionRepository(string dsn, ISpecificationFinder specFinder, string[] indexedSegments, string schema = "dbo", string commonSchema = "dbo", int segmentBatchSize = 1000, string sqlDateType = "date")
     : base(dsn, schema)
 {
     _commonDb      = new DbCreation <T>(dsn, commonSchema, sqlDateType);
     _transactionDb = new DbCreation <T>(dsn, schema, sqlDateType);
     _schemaEnsured = false;
     _batchSize     = segmentBatchSize;
     _segmentBatch  = new SegmentBatch <T>(this);
     _specs         = new Dictionary <string, SegmentSpecification>();
     foreach (var segmentId in indexedSegments)
     {
         var spec = specFinder.FindSegmentSpec("5010", segmentId.Trim());
         _specs.Add(segmentId.Trim(), spec);
     }
 }
Beispiel #2
0
 /// <summary>
 /// Initializes a new instance of the <see cref="SqlTransactionRepository"/> class
 /// </summary>
 /// <param name="dsn">Data source information</param>
 /// <param name="specFinder">Specification finder for data structure information</param>
 /// <param name="indexedSegments">Segments stored in database</param>
 /// <param name="identityType">Identity type</param>
 /// <param name="schema">Database schema for data access</param>
 /// <param name="commonSchema">Common database schema</param>
 /// <param name="segmentBatchSize">Number of segments to pull from database at a time</param>
 /// <param name="sqlDateType">"Date" type used by database</param>
 public SqlTransactionRepository(
     string dsn,
     ISpecificationFinder specFinder,
     string[] indexedSegments,
     Type identityType,
     string schema        = "dbo",
     string commonSchema  = "dbo",
     int segmentBatchSize = 1000,
     string sqlDateType   = "date")
     : base(dsn, identityType, schema)
 {
     this.CommonDb      = new DbCreation(dsn, commonSchema, identityType, sqlDateType);
     this.TransactionDb = new DbCreation(dsn, schema, identityType, sqlDateType);
     this.idProvider    = this.GetIdProvider(dsn, commonSchema, identityType, segmentBatchSize / 10);
     this.schemaEnsured = false;
     this.batchSize     = segmentBatchSize;
     this.SegmentBatch  = new SegmentBatch(this, identityType);
     this.specs         = new Dictionary <string, SegmentSpecification>();
     foreach (var segmentId in indexedSegments)
     {
         var spec = specFinder.FindSegmentSpec("5010", segmentId.Trim());
         this.specs.Add(segmentId.Trim(), spec);
     }
 }
        protected virtual TransactionSetResponse AcknowledgeTransaction(X12StreamReader reader, string functionalCode, string versionIdentifierCode, string transaction)
        {
            string[] stElements = reader.SplitSegment(transaction);
            var      response   = new TransactionSetResponse
            {
                TransactionSetIdentifierCode = stElements[1],
                TransactionSetControlNumber  = stElements[2]
            };

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

            var transactionSpec = _specFinder.FindTransactionSpec(functionalCode, versionIdentifierCode, response.TransactionSetIdentifierCode);

            if (transactionSpec == null)
            {
                response.SyntaxErrorCodes.Add("1"); // Transaction Set Not Supported
                response.AcknowledgmentCode = AcknowledgmentCodeEnum.R_Rejected;
                return(response);
            }

            #region Validate against transaction specification
            Stack <ContainerInformation> containers = new Stack <ContainerInformation>();
            var transactionContainer = new ContainerInformation {
                Spec = transactionSpec
            };
            containers.Push(transactionContainer);

            List <SegmentInformation> segmentInfos = new List <SegmentInformation>();
            string[] segments = transaction.Split(new char[] { reader.Delimiters.SegmentTerminator }, 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 = _specFinder.FindSegmentSpec(versionIdentifierCode, segmentInfo.SegmentId);
                segmentInfos.Add(segmentInfo);

                ContainerInformation currentContainer = containers.Peek();

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

                case "HL":
                    string hlNumber       = segmentInfo.Elements[1];
                    string hlParentNumber = segmentInfo.Elements[2];
                    string hlLevelCode    = segmentInfo.Elements[3];
                    var    hlSpec         = transactionSpec.HierarchicalLoopSpecifications.FirstOrDefault(hls => hls.LevelCode == hlLevelCode);
                    if (hlSpec != null)
                    {
                        while (!(containers.Peek().Spec is TransactionSpecification))
                        {
                            if (containers.Peek().HLoopNumber == hlParentNumber)
                            {
                                break;
                            }
                            containers.Pop();
                        }
                        segmentInfo.LoopId = hlSpec.LoopId;
                        var hlContainer = new ContainerInformation {
                            Spec = hlSpec, HLoopNumber = hlNumber
                        };
                        hlContainer.Segments.Add(segmentInfo);
                        containers.Peek().Containers.Add(hlContainer);
                        containers.Push(hlContainer);
                    }
                    else
                    {
                        response.SegmentErrors.Add(CreateDataElementError(segmentInfo, 3, "I6", hlLevelCode)); //Code Value Not Used in Implementation
                        response.AcknowledgmentCode = AcknowledgmentCodeEnum.X_Rejected_ContentCouldNotBeAnalyzed;
                        return(response);                                                                      // end validation if HL cannot be recognized since hl spec will not be available
                    }
                    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 = null;
                            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(CreateSegmentError(segmentInfo, "6"));     //Segment Not in Defined Transaction Set
                                response.AcknowledgmentCode = AcknowledgmentCodeEnum.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(CreateSegmentError(segmentInfo, "2")); // Unexpected segment
                                response.AcknowledgmentCode = AcknowledgmentCodeEnum.X_Rejected_ContentCouldNotBeAnalyzed;
                                return(response);                                                 // end validation if unrecognized segment encountered (cannot guarantee we are pointing at correct container)
                            }
                            else
                            {
                                containers.Pop();
                                currentContainer = containers.Peek();
                            }
                        }
                    } while (!matchFound);
                    break;
                }
                response.SegmentErrors.AddRange(ValidateSegmentAgainstSpec(segmentInfo));
            }

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

            #endregion

            #region Validate transaction trailer
            var trailerSegment = segmentInfos.FirstOrDefault(si => si.SegmentId == "SE");
            if (trailerSegment == null)
            {
                response.SyntaxErrorCodes.Add("2"); //Transaction Set Trailer Missing
            }
            else
            {
                if (trailerSegment.Elements.Length <= 2 || trailerSegment.Elements[2] != response.TransactionSetControlNumber)
                {
                    response.SyntaxErrorCodes.Add("3"); // Transaction Set Control Number in Header and Trailer Do Not Match
                }
                if (trailerSegment.Elements.Length >= 2)
                {
                    int segmentCount;
                    int.TryParse(trailerSegment.Elements[1], out segmentCount);
                    if (segmentCount != segmentInfos.Count)
                    {
                        response.SyntaxErrorCodes.Add("4"); // Number of Included Segments Does Not Match Actual Count
                    }
                }
                else
                {
                    response.SyntaxErrorCodes.Add("4"); // Number of Included Segments Does Not Match Actual Count
                }
            }

            #endregion

            if (response.SegmentErrors.Count > 0 || response.SyntaxErrorCodes.Count > 0)
            {
                if (response.SegmentErrors.Count > 0)
                {
                    response.SyntaxErrorCodes.Add("5"); //One or More Segments in Error
                }
                if (response.AcknowledgmentCode == AcknowledgmentCodeEnum.A_Accepted)
                {
                    response.AcknowledgmentCode = AcknowledgmentCodeEnum.E_Accepted_ButErrorsWereNoted;
                }
            }
            return(response);
        }