Message IDocumentRepository.ProvideAndRegisterDocumentSet(Message msgRequest)
        {
            Message          msgResponse           = null;
            XmlDocument      xmlDocRequest         = null;
            XmlDocument      xmlDocResponse        = null;
            XmlNode          nodeRegistryError     = null;
            string           errorCode             = null;
            RepositoryLogic  repositoryLogic       = null;
            StringDictionary stringDictionary      = null;
            string           eventOutcomeIndicator = "0";
            string           submissionSetUniqueID = string.Empty;
            string           sourceUserID          = string.Empty;
            string           destinationUserID     = string.Empty;

            try
            {
                repositoryLogic = new RepositoryLogic();

                objDocumentRepositoryLog                   = new DocumentRepositoryLog();
                objDocumentRepositoryLog.StartTime         = DateTime.Now;
                objDocumentRepositoryLog.RequesterIdentity = Environment.UserName;

                //ATNA Event Source & Destination UserID
                sourceUserID      = GetSourceUserID();
                destinationUserID = GetDestinationUserID();

                //Request XmlDocument
                xmlDocRequest = new XmlDocument();
                xmlDocRequest.Load(msgRequest.GetReaderAtBodyContents());


                //Process Message will Construct Response for Register Transaction Set-B
                //Recieves a message from Provide and register document set B(With no errors from Repositrory)
                xmlDocResponse = ProcessProvideAndRegisterDocumentSet(xmlDocRequest, msgRequest.Headers.MessageVersion, out stringDictionary);

                //ATNA Event
                eventOutcomeIndicator = stringDictionary["$EventIdentification.EventOutcomeIndicator$"];
            }
            catch (ServerTooBusyException serverTooBusyException)
            {
                //Construct Error Response
                xmlDocResponse = CommonUtility.ConstructRegistryErrorResponse(GlobalValues.CONST_RESPONSE_STATUS_TYPE_FAILURE, string.Empty, GlobalValues.CONST_ERROR_CODE_XDSRepositoryTooBusyException, GlobalValues.CONST_ERROR_CODE_XDSRepositoryTooBusyException, GlobalValues.CONST_SEVERITY_TYPE_ERROR, string.Empty);

                nodeRegistryError = xmlDocResponse.SelectSingleNode(@"//*[local-name()='RegistryError']");
                errorCode         = nodeRegistryError.Attributes["errorCode"].Value;
                if (errorCode != null)
                {
                    repositoryLogic.LogRolledBackData(objDocumentRepositoryLog, errorCode);
                }

                //ATNA EVENT LOG
                eventOutcomeIndicator = "8";
            }
            catch (TimeoutException timeoutException)
            {
                //Construct Error Response
                xmlDocResponse = CommonUtility.ConstructRegistryErrorResponse(GlobalValues.CONST_RESPONSE_STATUS_TYPE_FAILURE, string.Empty, GlobalValues.CONST_ERROR_CODE_TimeOut, GlobalValues.CONST_ERROR_CODE_TimeOut, GlobalValues.CONST_SEVERITY_TYPE_ERROR, string.Empty);

                nodeRegistryError = xmlDocResponse.SelectSingleNode(@"//*[local-name()='RegistryError']");
                errorCode         = nodeRegistryError.Attributes["errorCode"].Value;
                if (errorCode != null)
                {
                    repositoryLogic.LogRolledBackData(objDocumentRepositoryLog, errorCode);
                }

                //ATNA EVENT LOG
                eventOutcomeIndicator = "8";
            }
            catch (System.ServiceModel.Security.SecurityAccessDeniedException AuthorizationException)
            {
                //Construct Error Response
                xmlDocResponse = CommonUtility.ConstructRegistryErrorResponse(GlobalValues.CONST_RESPONSE_STATUS_TYPE_FAILURE, string.Empty, GlobalValues.CONST_ERROR_CODE_XDSAuthorizationException, GlobalValues.CONST_ERROR_CODE_XDSAuthorizationException, GlobalValues.CONST_SEVERITY_TYPE_ERROR, string.Empty);

                nodeRegistryError = xmlDocResponse.SelectSingleNode(@"//*[local-name()='RegistryError']");
                errorCode         = nodeRegistryError.Attributes["errorCode"].Value;
                if (errorCode != null)
                {
                    repositoryLogic.LogRolledBackData(objDocumentRepositoryLog, errorCode);
                }

                //ATNA EVENT LOG
                eventOutcomeIndicator = "8";
            }
            catch (OutOfMemoryException RepositoryOutOfResources)
            {
                //Construct Error Response
                xmlDocResponse = CommonUtility.ConstructRegistryErrorResponse(GlobalValues.CONST_RESPONSE_STATUS_TYPE_FAILURE, string.Empty, GlobalValues.CONST_ERROR_CODE_XDSRepositoryOutOfResources, GlobalValues.CONST_ERROR_CODE_XDSRepositoryOutOfResources, GlobalValues.CONST_SEVERITY_TYPE_ERROR, string.Empty);

                nodeRegistryError = xmlDocResponse.SelectSingleNode(@"//*[local-name()='RegistryError']");
                errorCode         = nodeRegistryError.Attributes["errorCode"].Value;
                if (errorCode != null)
                {
                    repositoryLogic.LogRolledBackData(objDocumentRepositoryLog, errorCode);
                }

                //ATNA EVENT LOG
                eventOutcomeIndicator = "8";
            }
            catch (Exception ex)
            {
                if (ex.Message == GlobalValues.CONST_ERROR_CODE_XDSMissingDocumentMetadata)
                {
                    //Construct Error Response
                    xmlDocResponse = CommonUtility.ConstructRegistryErrorResponse(GlobalValues.CONST_RESPONSE_STATUS_TYPE_FAILURE, string.Empty, "XDSDocumentEntry document exists in metadata with no corresponding metatdata", GlobalValues.CONST_ERROR_CODE_XDSMissingDocumentMetadata, GlobalValues.CONST_SEVERITY_TYPE_ERROR, string.Empty);
                }
                else if (ex.Message == GlobalValues.CONST_ERROR_CODE_XDSMissingDocumentAttachment)
                {
                    //Construct Error Response
                    xmlDocResponse = CommonUtility.ConstructRegistryErrorResponse(GlobalValues.CONST_RESPONSE_STATUS_TYPE_FAILURE, string.Empty, "XDSDocumentEntry exists in metadata with no corresponding attached document", GlobalValues.CONST_ERROR_CODE_XDSMissingDocumentAttachment, GlobalValues.CONST_SEVERITY_TYPE_ERROR, string.Empty);
                }
                else if (ex.Message == GlobalValues.CONST_ERROR_CODE_XDSInvalidRequest)
                {
                    //Construct Error Response
                    xmlDocResponse = CommonUtility.ConstructRegistryErrorResponse(GlobalValues.CONST_RESPONSE_STATUS_TYPE_FAILURE, string.Empty, "XDSInvalidRequest - DcoumentId is not unique.", GlobalValues.CONST_ERROR_CODE_XDSInvalidRequest, GlobalValues.CONST_SEVERITY_TYPE_ERROR, string.Empty);
                }
                else if (ex.Message == GlobalValues.CONST_ERROR_CODE_XDSRepositoryMetadataError)
                {
                    //Construct Error Response
                    xmlDocResponse = CommonUtility.ConstructRegistryErrorResponse(GlobalValues.CONST_RESPONSE_STATUS_TYPE_FAILURE, string.Empty, "Error occurred in Parsing the Metadata.", GlobalValues.CONST_ERROR_CODE_XDSRepositoryMetadataError, GlobalValues.CONST_SEVERITY_TYPE_ERROR, string.Empty);
                }
                else if (ex.Message == GlobalValues.CONST_ERROR_CODE_XDSRegistryNotAvailable)
                {
                    //Construct Error Response
                    xmlDocResponse = CommonUtility.ConstructRegistryErrorResponse(GlobalValues.CONST_RESPONSE_STATUS_TYPE_FAILURE, string.Empty, "Repository was unable to access the Registry.", GlobalValues.CONST_ERROR_CODE_XDSRegistryNotAvailable, GlobalValues.CONST_SEVERITY_TYPE_ERROR, string.Empty);
                }
                else
                {
                    //Construct Error Response
                    xmlDocResponse = CommonUtility.ConstructRegistryErrorResponse(GlobalValues.CONST_RESPONSE_STATUS_TYPE_FAILURE, string.Empty, GlobalValues.CONST_ERROR_CODE_XDSRepositoryError, GlobalValues.CONST_ERROR_CODE_XDSRepositoryError, GlobalValues.CONST_SEVERITY_TYPE_ERROR, string.Empty);
                }

                nodeRegistryError = xmlDocResponse.SelectSingleNode(@"//*[local-name()='RegistryError']");

                errorCode = nodeRegistryError.Attributes["errorCode"].Value;
                if (errorCode != null)
                {
                    repositoryLogic.LogRolledBackData(objDocumentRepositoryLog, errorCode);
                }

                //ATNA EVENT LOG
                eventOutcomeIndicator = "8";
            }


            //ATNA EVENT LOG
            submissionSetUniqueID = stringDictionary["$SubmissionSet.UniqueID$"];

            //REPOSITORY-RDS-EXPORT-ITI-42
            repositoryLogic.ProcessRegisterDocumentSetATNAEvent(submissionSetUniqueID, sourceUserID, destinationUserID, eventOutcomeIndicator);
            //REPOSITORY-P-AND-R-IMPORT-ITI-41
            repositoryLogic.ProcessProvideAndRegisterATNAEvent(submissionSetUniqueID, sourceUserID, destinationUserID, eventOutcomeIndicator);

            msgResponse = Message.CreateMessage(msgRequest.Headers.MessageVersion, GlobalValues.CONST_ACTION_ProvideAndRegisterDocumentSet_bResponse, new XmlNodeReader(xmlDocResponse));

            return(msgResponse);
        }
        private XmlDocument ProcessProvideAndRegisterDocumentSet(XmlDocument xmlDocRequest, MessageVersion msgVersion, out StringDictionary atnaParameterValues)
        {
            XmlDocument          xmlDocRegistryRequest    = null;
            XmlDocument          xmlDocResponse           = null;
            Message              registryMessage          = null;
            XmlDocument          xmlDocRegistryResponse   = null;
            RepositoryLogic      repositoryLogic          = null;
            XmlElement           eltProvideAndRegDocSet   = null;
            XmlNode              nodeSubmitObjectsRequest = null;
            XmlNodeList          nodeListExtrinsicObject  = null;
            XmlNodeList          nodeListDocument         = null;
            XmlNode              nodeSubmissionSet        = null;
            XmlNode              nodeExternalIdentifier   = null;
            List <DocumentEntry> lstDocumentEntry         = null;
            StringBuilder        sbMetaData        = null;
            string xpathExternalIdentifierDocument = @".//*[local-name()='ExtrinsicObject'][@id='$id$']/*[local-name()='ExternalIdentifier'][@identificationScheme='$identificationScheme$']";
            string xpath                 = null;
            string entryUUID             = null;
            string uniqueID              = null;
            string eventOutcomeIndicator = "0";

            atnaParameterValues = new StringDictionary();

            try
            {
                repositoryLogic = new RepositoryLogic();
                xpathExternalIdentifierDocument = xpathExternalIdentifierDocument.Replace("$identificationScheme$", GlobalValues.XDSDocumentEntry_uniqueIdUUID);

                eltProvideAndRegDocSet = xmlDocRequest.DocumentElement;

                nodeListExtrinsicObject = eltProvideAndRegDocSet.SelectNodes(".//*[local-name()='ExtrinsicObject']");

                nodeListDocument = eltProvideAndRegDocSet.SelectNodes(".//*[local-name()='Document']");

                nodeSubmissionSet = eltProvideAndRegDocSet.SelectSingleNode("//*[local-name()='SubmitObjectsRequest']/*[local-name()=\"RegistryObjectList\"]/*[local-name()='RegistryPackage']/*[local-name()='ExternalIdentifier'][@identificationScheme='urn:uuid:96fdda7c-d067-4183-912e-bf5ee74998a8']/@value");

                if (nodeSubmissionSet != null)
                {
                    atnaParameterValues.Add("$SubmissionSet.UniqueID$", nodeSubmissionSet.Value);
                }

                //Proceed further only if any ExtrinsicObject Exists(with attachments)
                if (nodeListExtrinsicObject == null)
                {
                    throw new Exception();
                }

                //if (repositoryLogic.IsMissingDocumentAttachment(nodeListDocument, eltProvideAndRegDocSet))
                if (repositoryLogic.IsMissingDocumentAttachment(eltProvideAndRegDocSet))
                {
                    throw new Exception(GlobalValues.CONST_ERROR_CODE_XDSMissingDocumentAttachment);
                }

                //if (repositoryLogic.IsMissingDocumentMetadata(nodeListExtrinsicObject, eltProvideAndRegDocSet))
                if (repositoryLogic.IsMissingDocumentMetadata(eltProvideAndRegDocSet))
                {
                    throw new Exception(GlobalValues.CONST_ERROR_CODE_XDSMissingDocumentMetadata);
                }

#if debug
                if (!repositoryLogic.IsSchemaValid(xmlDocMsgBody))
                {
                    throw new Exception(GlobalValues.CONST_ERROR_CODE_XDSInvalidRequest);
                }
#endif

                if (repositoryLogic.IsDuplicateUniqueID(eltProvideAndRegDocSet))
                {
                    throw new Exception(GlobalValues.CONST_ERROR_CODE_XDSRepositoryDuplicateUniqueIdInMessage);
                }

                if (nodeListExtrinsicObject.Count > 0 && eltProvideAndRegDocSet.SelectNodes(@"//*[local-name()='Document']").Count > 0)
                {
                    //No document OR Metadata is Missing

                    lstDocumentEntry = new List <DocumentEntry>();
                    sbMetaData       = new StringBuilder();

                    foreach (XmlNode node in nodeListExtrinsicObject)
                    {
                        DocumentEntry objDocumentEntry = new DocumentEntry();

                        if (node.Attributes["mimeType"].Value == string.Empty)
                        {
                            throw new Exception(GlobalValues.CONST_ERROR_CODE_XDSRepositoryMetadataError);
                        }

                        objDocumentEntry.MimeType = node.Attributes["mimeType"].Value;

                        entryUUID = node.Attributes["id"].Value;
                        xpath     = xpathExternalIdentifierDocument.Replace("$id$", node.Attributes["id"].Value);
                        nodeExternalIdentifier = eltProvideAndRegDocSet.SelectSingleNode(xpath);
                        uniqueID = nodeExternalIdentifier.Attributes["value"].Value;

                        if (string.IsNullOrEmpty(uniqueID))
                        {
                            throw new Exception(GlobalValues.CONST_ERROR_CODE_XDSRepositoryMetadataError);
                        }

                        if (!repositoryLogic.IsValidUniqueID(uniqueID))
                        {
                            throw new Exception(GlobalValues.CONST_ERROR_CODE_XDSInvalidRequest);
                        }

                        objDocumentEntry.EntryUUID = entryUUID;
                        objDocumentEntry.UniqueID  = uniqueID;
                        objDocumentEntry.Hash      = repositoryLogic.GetHashCode(xmlDocRequest, entryUUID);
                        objDocumentEntry.Content   = repositoryLogic.GetDocumentContentStream(xmlDocRequest, entryUUID);
                        objDocumentEntry.Size      = (int)objDocumentEntry.Content.Length;

                        lstDocumentEntry.Add(objDocumentEntry);

                        sbMetaData.Append(node.OuterXml);
                    }

                    //Logging the Repository Data
                    objDocumentRepositoryLog.RequestMetadata = sbMetaData.ToString();

                    using (TransactionScope provideAndRegSetBScope = new TransactionScope())
                    {
                        //Information Logged in the Document Repository Log
                        objDocumentRepositoryLog.EndTime = DateTime.Now;
                        objDocumentRepositoryLog.Result  = "OK";
                        int noOfRows = repositoryLogic.LogRepositoryData(objDocumentRepositoryLog);
                        for (int docElement = 0; docElement < lstDocumentEntry.Count; docElement++)
                        {
                            string sStorageUniqueIdentifier = string.Empty;

                            DocumentEntry objDocEntry = lstDocumentEntry[docElement];

                            sStorageUniqueIdentifier = SQLServerStorageService.SaveDocument(objDocEntry.Content, objDocEntry.UniqueID);

                            //Save Metadata
                            repositoryLogic.SaveMetaData(objDocEntry);

                            //Insert into Document Entry Log
                            repositoryLogic.LogDocumentEntry();
                        }
                        //Create SLots for Repository ID,,Hash and Size and send those to
                        //Register document Set B
                        //this Array list already contains all ID's
                        if (lstDocumentEntry.Count > 0)
                        {
                            string repositoryUniqueId = repositoryLogic.GetRepositoryUniqueID("repositoryUniqueID");
                            string repositoryURI      = string.Empty;

                            for (int docID = 0; docID < lstDocumentEntry.Count; docID++)
                            {
                                DocumentEntry objDocumentEntry = lstDocumentEntry[docID];

                                //Creates Slots to add Medatada repositoryUniqueId
                                xmlDocRequest = repositoryLogic.CreateRepositorySlotElement(xmlDocRequest, "repositoryUniqueId", repositoryUniqueId, objDocumentEntry.EntryUUID);

                                //Creates Slots to add Medatada hash
                                xmlDocRequest = repositoryLogic.CreateRepositorySlotElement(xmlDocRequest, "hash", objDocumentEntry.Hash, objDocumentEntry.EntryUUID);

                                //Creates Slots to add Medatada size
                                xmlDocRequest = repositoryLogic.CreateRepositorySlotElement(xmlDocRequest, "size", objDocumentEntry.Content.Length.ToString(), objDocumentEntry.EntryUUID);

                                //Creates Slots to add Medatada URI
                                xmlDocRequest = repositoryLogic.CreateRepositorySlotElement(xmlDocRequest, "URI", repositoryURI, objDocumentEntry.EntryUUID);
                            }
                        }
                        //Message to be sent to Registry
                        try
                        {
                            //Sample RegistryResponse  - <RegistryResponse xmlns="urn:oasis:names:tc:ebxml-regrep:xsd:rs:3.0" />;
                            //Call the XDSRegistry Service
                            Message provideAndResgiterSetInput = null;
                            string  xdsRegistryEndpointName    = CommonUtility.GetXDSRegistryEndpointName();
                            xmlDocRegistryRequest    = new XmlDocument();
                            nodeSubmitObjectsRequest = xmlDocRequest.SelectSingleNode(@"//*[local-name()='SubmitObjectsRequest']");
                            xmlDocRegistryRequest.LoadXml(nodeSubmitObjectsRequest.OuterXml);
                            XDSRegistry.XDSRegistryClient objRegsitryClient = new Microsoft.IHE.XDS.DocumentRepository.XDSRegistry.XDSRegistryClient(xdsRegistryEndpointName);
                            provideAndResgiterSetInput = Message.CreateMessage(msgVersion, GlobalValues.CONST_ACTION_REGISTERDOCUMENTSETB, new XmlNodeReader(xmlDocRegistryRequest));
                            registryMessage            = objRegsitryClient.RegisterDocumentSet(provideAndResgiterSetInput);
                        }
                        catch
                        {
                            throw new Exception("XDSRegistryNotAvailable");
                        }


                        xmlDocRegistryResponse = new XmlDocument();
                        xmlDocRegistryResponse.Load(registryMessage.GetReaderAtBodyContents());

                        XmlNode errorList = xmlDocRegistryResponse.SelectSingleNode(@"//*[local-name()='RegistryError']");
                        string  errorCode = null;

                        if (errorList != null)
                        {
                            errorCode = errorList.Attributes["errorCode"].Value;
                        }

                        //Move this outside TransactionScope...the log entry is rolled back
                        //Code block within TransactionScope should be
                        //if (errorCode == null)
                        //{
                        //    provideAndRegSetBScope.Complete();
                        //}
                        //Code block outside TransactionScope should be
                        //if (errorCode != null)
                        //{
                        //    repositoryLogic.LogRolledBackData(objDocumentRepositoryLog, errorCode);

                        //    //ATNA Failure Code
                        //    eventOutcomeIndicator = "8";
                        //}


                        if (errorCode != null)
                        {
                            repositoryLogic.LogRolledBackData(objDocumentRepositoryLog, errorCode);

                            //ATNA Failure Code
                            eventOutcomeIndicator = "8";
                        }
                        else
                        {
                            provideAndRegSetBScope.Complete();
                        }

                        //Assign Registry Response to Repository Response
                        xmlDocResponse = xmlDocRegistryResponse;

                        //Transaction is completed
                    }
                }
                else
                {
                    //Get Message from Registry
                    try
                    {
                        //Sample RegistryResponse - <RegistryResponse xmlns="urn:oasis:names:tc:ebxml-regrep:xsd:rs:3.0" />;
                        //Call the XDSRegistry Service
                        Message msgProvideAndResgiterSetInput = null;
                        string  xdsRegistryEndpointName       = CommonUtility.GetXDSRegistryEndpointName();
                        xmlDocRegistryRequest    = new XmlDocument();
                        nodeSubmitObjectsRequest = xmlDocRequest.SelectSingleNode(@"//*[local-name()='SubmitObjectsRequest']");
                        xmlDocRegistryRequest.LoadXml(nodeSubmitObjectsRequest.OuterXml);
                        XDSRegistry.XDSRegistryClient objRegsitryClient = new Microsoft.IHE.XDS.DocumentRepository.XDSRegistry.XDSRegistryClient(xdsRegistryEndpointName);
                        msgProvideAndResgiterSetInput = Message.CreateMessage(msgVersion, GlobalValues.CONST_ACTION_REGISTERDOCUMENTSETB, new XmlNodeReader(xmlDocRegistryRequest));
                        registryMessage = objRegsitryClient.RegisterDocumentSet(msgProvideAndResgiterSetInput);
                    }
                    catch
                    {
                        throw new Exception("XDSRegistryNotAvailable");
                    }

                    xmlDocRegistryResponse = new XmlDocument();
                    xmlDocRegistryResponse.Load(registryMessage.GetReaderAtBodyContents());

                    XmlNode errorList = xmlDocRegistryResponse.SelectSingleNode(@"//*[local-name()='RegistryError']");
                    string  errorCode = null;

                    if (errorList != null)
                    {
                        errorCode = errorList.Attributes["errorCode"].Value;
                    }


                    if (errorCode != null)
                    {
                        repositoryLogic.LogRolledBackData(objDocumentRepositoryLog, errorCode);

                        //ATNA Failure Code
                        eventOutcomeIndicator = "8";
                    }

                    //Assign Registry Response to Repository Response
                    xmlDocResponse = xmlDocRegistryResponse;
                }
            }
            catch
            {
                throw;
            }

            atnaParameterValues.Add("$EventIdentification.EventOutcomeIndicator$", eventOutcomeIndicator);

            return(xmlDocResponse);
        }