The abstract upload context
        public static RopResult GetContentsTable(int serverId, int folderHandleIndex, DeleteFlags deleteFlags, out int rowCount)
        {
            // The construction conditions.
            Condition.IsTrue(connections.Count > 0);
            Condition.IsTrue(connections.Keys.Contains(serverId));

            // Get current ConnectionData value.
            ConnectionData currentConnection = connections[serverId];

            // Create a new currentDownloadContext.
            AbstractUploadInfo currentUploadContext = new AbstractUploadInfo();
            rowCount = -1;

            // Find the current Upload Context
            foreach (AbstractUploadInfo tempUploadContext in currentConnection.UploadContextContainer)
            {
                if (tempUploadContext.RelatedFastTransferOperation == EnumFastTransferOperation.SynchronizationImportDeletes)
                {
                    currentUploadContext = tempUploadContext;
                }
            }

            if (folderHandleIndex < 0)
            {
                rowCount = -1;

                // serverHandleIndex is Invalid Parameter.
                return RopResult.InvalidParameter;
            }
            else
            {
                if (deleteFlags == DeleteFlags.Initial)
                {
                    rowCount = 0;
                    return RopResult.Success;
                }
                else if (deleteFlags == DeleteFlags.HardDeleteCheck)
                {
                    rowCount = 0;
                }
                else if (deleteFlags == DeleteFlags.SoftDeleteCheck)
                {
                    rowCount = softDeleteMessageCount;
                    if (priorOperation == MS_OXCFXICS.PriorOperation.RopSynchronizationImportMessageMove)
                    {
                        rowCount = 1;
                    }
                }

                return RopResult.Success;
            }
        }
        public static RopResult GetHierarchyTable(int serverId, int folderHandleIndex, DeleteFlags deleteFlags, out int rowCount)
        {
            // The construction conditions.
            Condition.IsTrue(connections.Count > 0);
            Condition.IsTrue(connections.Keys.Contains(serverId));

            // Get current ConnectionData value.
            ConnectionData currentConnection = connections[serverId];

            // Create a new currentDownloadContext.
            AbstractUploadInfo currentUploadContext = new AbstractUploadInfo();

            // Initialize the rowCount value.
            rowCount = -1;

            // Find the current Upload Context
            foreach (AbstractUploadInfo tempUploadContext in currentConnection.UploadContextContainer)
            {
                if (tempUploadContext.RelatedFastTransferOperation == EnumFastTransferOperation.SynchronizationImportDeletes)
                {
                    currentUploadContext = tempUploadContext;
                }
            }

            if (folderHandleIndex < 0)
            {
                rowCount = -1;

                // serverHandleIndex is Invalid Parameter.
                return RopResult.InvalidParameter;
            }
            else
            {
                if (deleteFlags == DeleteFlags.Initial)
                {
                    rowCount = 0;
                    return RopResult.Success;
                }
                else if (deleteFlags == DeleteFlags.HardDeleteCheck)
                {
                    if (requirementContainer.ContainsKey(90205002) && !requirementContainer[90205002])
                    {
                        rowCount = -1;
                    }
                    else
                    {
                        rowCount = 0;
                    }
                }
                else if (deleteFlags == DeleteFlags.SoftDeleteCheck)
                {
                    rowCount = softDeleteFolderCount;
                }

                return RopResult.Success;
            }
        }
        public static RopResult SynchronizationUploadState(int serverId, int uploadContextHandleIndex, ICSStateProperties icsPropertyType, bool isPidTagIdsetGivenInputAsInter32, int icsStateIndex)
        {
            // The contractions conditions.
            Condition.IsTrue(connections.Count > 0);
            Condition.IsTrue(connections.Keys.Contains(serverId));
            Condition.IsTrue(connections[serverId].DownloadContextContainer.Count > 0 || connections[serverId].UploadContextContainer.Count > 0);

            // Initialize the return value.
            RopResult result = RopResult.InvalidParameter;
            AbstractUploadInfo uploadInfo = new AbstractUploadInfo();
            AbstractDownloadInfo downLoadInfo = new AbstractDownloadInfo();

            // Get the current ConnectionData value.
            ConnectionData changeConnection = connections[serverId];

            // Identify whether the DownloadContext or UploadContext is existent or not and record the index.
            bool isCurrentUploadinfoExist = false;
            int currentUploadIndex = 0;
            bool isCurrentDownLoadinfoExist = false;
            int currentDownLoadIndex = 0;

            foreach (AbstractUploadInfo tempUploadInfo in changeConnection.UploadContextContainer)
            {
                if (tempUploadInfo.UploadHandleIndex == uploadContextHandleIndex)
                {
                    // Set the value to the related variable when the current upload context is existent.
                    isCurrentUploadinfoExist = true;
                    uploadInfo = tempUploadInfo;
                    currentUploadIndex = changeConnection.UploadContextContainer.IndexOf(tempUploadInfo);
                    break;
                }
            }

            if (!isCurrentUploadinfoExist)
            {
                foreach (AbstractDownloadInfo tempDownLoadInfo in changeConnection.DownloadContextContainer)
                {
                    if (tempDownLoadInfo.DownloadHandleIndex == uploadContextHandleIndex)
                    {
                        // Set the value to the related variable when the current Download context is existent.
                        isCurrentDownLoadinfoExist = true;
                        downLoadInfo = tempDownLoadInfo;
                        currentDownLoadIndex = changeConnection.DownloadContextContainer.IndexOf(tempDownLoadInfo);
                        break;
                    }
                }
            }

            if (isCurrentDownLoadinfoExist || isCurrentUploadinfoExist)
            {
                if (isCurrentUploadinfoExist)
                {
                    if (icsStateIndex != 0)
                    {
                        AbstractFolder currentFolder = new AbstractFolder();
                        foreach (AbstractFolder tempFolder in changeConnection.FolderContainer)
                        {
                            if (tempFolder.FolderHandleIndex == uploadInfo.RelatedObjectHandleIndex)
                            {
                                // Set the value to the related variable when the current Folder is existent.
                                currentFolder = tempFolder;
                                Condition.IsTrue(currentFolder.ICSStateContainer.ContainsKey(icsStateIndex));
                            }
                        }

                        // Add ICS State to ICSStateContainer of current folder.
                        AbstractUpdatedState updatedState = currentFolder.ICSStateContainer[icsStateIndex];
                        switch (icsPropertyType)
                        {
                            case ICSStateProperties.PidTagIdsetGiven:

                                // Set IdsetGiven value
                                uploadInfo.UpdatedState.IdsetGiven = updatedState.IdsetGiven;
                                break;
                            case ICSStateProperties.PidTagCnsetRead:

                                // Set CnsetRead value
                                uploadInfo.UpdatedState.CnsetRead = updatedState.CnsetRead;
                                break;
                            case ICSStateProperties.PidTagCnsetSeen:

                                // Set CnsetSeen value
                                uploadInfo.UpdatedState.CnsetSeen = updatedState.CnsetSeen;
                                break;
                            case ICSStateProperties.PidTagCnsetSeenFAI:

                                // Set CnsetSeenFAI value
                                uploadInfo.UpdatedState.CnsetSeenFAI = updatedState.CnsetSeenFAI;
                                break;
                            default:
                                break;
                        }

                        // Update the UploadContextContainer context.
                        changeConnection.UploadContextContainer = changeConnection.UploadContextContainer.Update(currentUploadIndex, uploadInfo);
                    }
                }
                else
                {
                    if (icsStateIndex != 0)
                    {
                        AbstractFolder currentFolder = new AbstractFolder();
                        foreach (AbstractFolder tempFolder in changeConnection.FolderContainer)
                        {
                            if (tempFolder.FolderHandleIndex == downLoadInfo.RelatedObjectHandleIndex)
                            {
                                // Set the value to the related variable when the current Folder is existent.
                                currentFolder = tempFolder;

                                // Identify ICS State whether exist index or not  in ICSStateContainer
                                Condition.IsTrue(currentFolder.ICSStateContainer.ContainsKey(icsStateIndex));
                            }
                        }

                        // Add update state to ICSStateContainer of current folder.
                        AbstractUpdatedState updatedState = currentFolder.ICSStateContainer[icsStateIndex];
                        switch (icsPropertyType)
                        {
                            case ICSStateProperties.PidTagIdsetGiven:

                                // Set IdsetGiven value.
                                downLoadInfo.UpdatedState.IdsetGiven = updatedState.IdsetGiven;
                                break;
                            case ICSStateProperties.PidTagCnsetRead:

                                // Set CnsetRead value.
                                downLoadInfo.UpdatedState.CnsetRead = updatedState.CnsetRead;
                                break;
                            case ICSStateProperties.PidTagCnsetSeen:

                                // Set CnsetSeen value.
                                downLoadInfo.UpdatedState.CnsetSeen = updatedState.CnsetSeen;
                                break;
                            case ICSStateProperties.PidTagCnsetSeenFAI:

                                // Set CnsetSeenFAI value.
                                downLoadInfo.UpdatedState.CnsetSeenFAI = updatedState.CnsetSeenFAI;
                                break;
                            default:
                                break;
                        }

                        // Update the DownloadContextContainer.
                        changeConnection.DownloadContextContainer = changeConnection.DownloadContextContainer.Update(currentDownLoadIndex, downLoadInfo);
                    }
                }

                connections[serverId] = changeConnection;
                if (isPidTagIdsetGivenInputAsInter32)
                {
                    // Identify the property tag whether PtypInteger32 is or not.
                    if (requirementContainer.Keys.Contains(2657) && requirementContainer[2657])
                    {
                        result = RopResult.Success;
                        ModelHelper.CaptureRequirement(2657, "[In Receiving the MetaTagIdsetGiven ICS State Property] Implementation does accept this MetaTagIdsetGiven property when the property tag identifies it as PtypInteger32. (Microsoft Exchange Server 2007 and above follow this behavior.)");
                    }
                    else
                    {
                        return result;
                    }
                }

                result = RopResult.Success;
            }

            return result;
        }
        public static RopResult FastTransferDestinationConfigure(int serverId, int objHandleIndex, SourceOperation option, FastTransferDestinationConfigureCopyFlags copyFlag, out int uploadContextHandleIndex)
        {
            // The construction conditions.
            Condition.IsTrue(connections.Count > 0);
            Condition.IsTrue(connections.Keys.Contains(serverId));

            // Initialize return value.
            RopResult result = RopResult.InvalidParameter;

            if (requirementContainer.ContainsKey(3492001))
            {
                if ((copyFlag == FastTransferDestinationConfigureCopyFlags.Invalid) &&
                    requirementContainer[3492001] == true)
                {
                    // FastTransferDestinationConfigureCopyFlags is invalid parameter and exchange server version is not ExchangeServer2007 .
                    uploadContextHandleIndex = -1;
                    ModelHelper.CaptureRequirement(
                                  3492001,
                                  @"[In Appendix A: Product Behavior] If unknown flags in the CopyFlags field are set, implementation does fail the operation. <36> Section 3.2.5.8.2.1: Exchange 2010, Exchange 2013 and Exchange 2016 fail the ROP [RopFastTransferDestinationConfigure ROP] if unknown bit flags in the CopyFlags field are set.");

                    return result;
                }
            }

            if (option == SourceOperation.CopyProperties || option == SourceOperation.CopyTo || option == SourceOperation.CopyFolder || option == SourceOperation.CopyMessages)
            {
                priorOperation = MS_OXCFXICS.PriorOperation.RopFastTransferDestinationConfigure;
            }

            sourOperation = option;

            // Create a new Upload context.
            AbstractUploadInfo uploadInfo = new AbstractUploadInfo();

            // Set value for upload context.
            uploadContextHandleIndex = AdapterHelper.GetHandleIndex();
            uploadInfo.UploadHandleIndex = uploadContextHandleIndex;
            ConnectionData changeConnection = connections[serverId];
            connections.Remove(serverId);

            // Add the new Upload context to UploadContextContainer.
            changeConnection.UploadContextContainer = changeConnection.UploadContextContainer.Add(uploadInfo);
            connections.Add(serverId, changeConnection);
            result = RopResult.Success;
            ModelHelper.CaptureRequirement(
                   581,
                   @"[In RopFastTransferDestinationConfigure ROP] The RopFastTransferDestinationConfigure ROP ([MS-OXCROPS] section 2.2.12.1) initializes a FastTransfer operation for uploading content encoded in a client-provided FastTransfer stream into a mailbox.");
            if (requirementContainer.ContainsKey(3492002))
            {
                if ((copyFlag == FastTransferDestinationConfigureCopyFlags.Invalid) &&
                    requirementContainer[3492002] == true)
                {
                    // Exchange 2007 ignore unknown values of the CopyFlags field.
                    ModelHelper.CaptureRequirement(
                                  3492002,
                                  @"[In Appendix A: Product Behavior] If unknown flags in the CopyFlags field are set, implementation does not fail the operation. <37> Section 3.2.5.8.2.1: Exchange 2007 ignore unknown values of the CopyFlags field.");

                    return result;
                }
            }

            return result;
        }
        public static RopResult SynchronizationImportMessageMove(int serverId, int synchronizationUploadContextHandleIndex, int sourceFolderIdIndex, int destinationFolderIdIndex, int sourceMessageIdIndex, int sourceFolderHandleIndex, int destinationFolderHandleIndex, bool inewerClientChange, out bool iolderversion, out bool icnpc)
        {
            // The contractions conditions.
            Condition.IsTrue(connections.Count > 0);
            Condition.IsTrue(connections.Keys.Contains(serverId));
            Condition.IsTrue(connections[serverId].FolderContainer.Count > 1);

            // Initialize the return value.
            RopResult result = RopResult.InvalidParameter;
            iolderversion = false;
            icnpc = false;

            // Get the current ConnectionData value.
            ConnectionData changeConnection = connections[serverId];

            // Identify whether Current Upload information is existent or not.
            bool isCurrentUploadinfoExist = false;

            // Record the current Upload information.
            int currentUploadIndex = 0;
            AbstractUploadInfo uploadInfo = new AbstractUploadInfo();
            foreach (AbstractUploadInfo tempUploadInfo in changeConnection.UploadContextContainer)
            {
                if (tempUploadInfo.UploadHandleIndex == synchronizationUploadContextHandleIndex)
                {
                    // Set the value for current upload information when  current upload Information is existent.
                    isCurrentUploadinfoExist = true;
                    uploadInfo = tempUploadInfo;
                    currentUploadIndex = changeConnection.UploadContextContainer.IndexOf(tempUploadInfo);
                }
            }

            // Create variable of relate to source Folder.
            AbstractFolder sourceFolder = new AbstractFolder();
            bool isSourceFolderExist = false;
            int sourceFolderIndex = 0;

            // Create variable of relate to destination Folder.
            AbstractFolder destinationFolder = new AbstractFolder();
            bool isdestinationFolderExist = false;
            int destinationFolderIndex = 0;

            // Create a new message.
            AbstractMessage movedMessage = new AbstractMessage();

            // Identify whether the Moved Message is existent or not.
            bool isMovedMessageExist = false;
            int movedMessageIndex = 0;

            foreach (AbstractFolder tempFolder in changeConnection.FolderContainer)
            {
                if (tempFolder.FolderIdIndex == sourceFolderIdIndex && tempFolder.FolderHandleIndex == sourceFolderHandleIndex)
                {
                    // Set the value to the variable when the source folder is existent.
                    isSourceFolderExist = true;
                    sourceFolder = tempFolder;
                    sourceFolderIndex = changeConnection.FolderContainer.IndexOf(tempFolder);
                }
            }

            foreach (AbstractFolder tempFolder in changeConnection.FolderContainer)
            {
                if (tempFolder.FolderIdIndex == destinationFolderIdIndex && tempFolder.FolderHandleIndex == destinationFolderHandleIndex)
                {
                    // Set the value to the related variable when the destination folder is existent.
                    isdestinationFolderExist = true;
                    destinationFolder = tempFolder;
                    destinationFolderIndex = changeConnection.FolderContainer.IndexOf(tempFolder);
                }
            }

            foreach (AbstractMessage tempMessage in changeConnection.MessageContainer)
            {
                if (tempMessage.MessageIdIndex == sourceMessageIdIndex)
                {
                    // Set the value to the related variable when the source Message is existent.
                    isMovedMessageExist = true;
                    movedMessage = tempMessage;
                    movedMessageIndex = changeConnection.MessageContainer.IndexOf(tempMessage);
                }
            }

            if (isSourceFolderExist && isdestinationFolderExist && isMovedMessageExist && isCurrentUploadinfoExist)
            {
                // Set value for the new abstract message property.
                movedMessage.FolderIdIndex = destinationFolder.FolderIdIndex;
                movedMessage.FolderHandleIndex = destinationFolder.FolderHandleIndex;

                // Assigned a new change. 
                movedMessage.ChangeNumberIndex = ModelHelper.GetChangeNumberIndex();

                // Assigned a new message id.
                movedMessage.MessageIdIndex = AdapterHelper.GetObjectIdIndex();

                // Update message Container.
                changeConnection.MessageContainer = changeConnection.MessageContainer.Update(movedMessageIndex, movedMessage);

                // Remove the current message id from MessageIds of source folder.
                sourceFolder.MessageIds = sourceFolder.MessageIds.Remove(movedMessage.MessageIdIndex);
                changeConnection.FolderContainer = changeConnection.FolderContainer.Update(sourceFolderIndex, sourceFolder);

                // Remove the current message id from MessageIds of destination Folder.
                destinationFolder.MessageIds = destinationFolder.MessageIds.Add(movedMessage.MessageIdIndex);
                changeConnection.FolderContainer = changeConnection.FolderContainer.Update(destinationFolderIndex, destinationFolder);

                // Add information of Upload context
                uploadInfo.IsnewerClientChange = inewerClientChange;
                uploadInfo.RelatedFastTransferOperation = EnumFastTransferOperation.SynchronizationImportMessageMove;

                // Update the upload context container
                changeConnection.UploadContextContainer = changeConnection.UploadContextContainer.Update(currentUploadIndex, uploadInfo);
                connections[serverId] = changeConnection;

                // Identify whether the IsnewerClientChange is true or false.
                if (uploadInfo.IsnewerClientChange == false)
                {
                    result = RopResult.Success;

                    ModelHelper.CaptureRequirement(
                        2449,
                        @"[In Uploading Changes Using ICS] Value is Success indicates No error occurred, or a conflict has been resolved.");

                    // Because if the result is success means the information about moving a message between two existing folders within the same mailbox imported
                    ModelHelper.CaptureRequirement(
                        839,
                        @"[In RopSynchronizationImportMessageMove ROP] The RopSynchronizationImportMessageMove ROP ([MS-OXCROPS] section 2.2.13.6) imports information about moving a message between two existing folders within the same mailbox.");
                }
                else
                {
                    // Set out put parameter value
                    iolderversion = true;
                    ModelHelper.CaptureRequirement(
                        875,
                        @"[In RopSynchronizationImportMessageMove ROP Response Buffer] [ 
Return value (4 bytes):] The following table[In section 2.2.3.2.4.4] contains additional return values[NewerClientChange] , if the ROP succeeded, but the server replica had an older version of a message than the local replica, the return value is 0x00040821.");
                    icnpc = true;
                    ModelHelper.CaptureRequirement(
                        876,
                        @"[In RopSynchronizationImportMessageMove ROP Response Buffer] [ 
Return value (4 bytes):] The following table[In section 2.2.3.2.4.4] contains additional return values[NewerClientChange] , if the values of the ChangeNumber and PredecessorChangeList fields, specified in section 2.2.3.2.4.4.1, were not applied to the destination message, the return value is 0x00040821.");
                    ModelHelper.CaptureRequirement(
                        1892,
                        "[In Identifying Objects and Maintaining Change Numbers]Copying of messaging objects within a mailbox or moving messages between folders of the same mailbox translates into creation of new messaging objects and therefore, new internal identifiers MUST be assigned to new copies.");
                    result = RopResult.NewerClientChange;
                }

                // Record RopSynchronizationImportMessageMove operation.
                priorUploadOperation = PriorOperation.RopSynchronizationImportMessageMove;
            }

            return result;
        }
        public static RopResult SynchronizationGetTransferState(int serverId, int syncHandleIndex, out int downloadcontextHandleIndex)
        {
            // The contractions conditions.
            Condition.IsTrue(connections.Count > 0);
            Condition.IsTrue(connections.Keys.Contains(serverId));
            Condition.IsTrue(connections[serverId].UploadContextContainer.Count > 0 || connections[serverId].DownloadContextContainer.Count > 0);

            // Initialize the return value.
            RopResult result = RopResult.InvalidParameter;
            downloadcontextHandleIndex = -1;

            // Get the current ConnectionData value.
            ConnectionData changeConnection = connections[serverId];
            AbstractDownloadInfo downloadInfo = new AbstractDownloadInfo();
            AbstractUploadInfo uploadInfo = new AbstractUploadInfo();

            // Identify whether the Download context or Upload context is existent or not and record the index.
            bool isCurrentDownloadInfoExist = false;
            bool isCurrentUploadInfoExist = false;

            foreach (AbstractDownloadInfo temp in changeConnection.DownloadContextContainer)
            {
                if (temp.DownloadHandleIndex == syncHandleIndex)
                {
                    // Set the value to the related variable when the current Download context is existent.
                    isCurrentDownloadInfoExist = true;
                    downloadInfo = temp;
                }
            }

            if (!isCurrentDownloadInfoExist)
            {
                foreach (AbstractUploadInfo tempInfo in changeConnection.UploadContextContainer)
                {
                    if (tempInfo.UploadHandleIndex == syncHandleIndex)
                    {
                        // Set the value to the related variable when the current upload context is existent.
                        isCurrentUploadInfoExist = true;
                        uploadInfo = tempInfo;
                    }
                }
            }

            if (isCurrentDownloadInfoExist || isCurrentUploadInfoExist)
            {
                // Create a new download context.
                AbstractDownloadInfo newDownloadInfo = new AbstractDownloadInfo
                {
                    DownloadHandleIndex = AdapterHelper.GetHandleIndex()
                };

                // Out the new downloadHandle.
                downloadcontextHandleIndex = newDownloadInfo.DownloadHandleIndex;
                ModelHelper.CaptureRequirement(765, "[In RopSynchronizationGetTransferState ROP Response Buffer]OutputServerObject: The value of this field MUST be the FastTransfer download context for the ICS state.");
                if (isCurrentDownloadInfoExist)
                {
                    // Set the new Download context value
                    newDownloadInfo.RelatedObjectHandleIndex = downloadInfo.RelatedObjectHandleIndex;
                    newDownloadInfo.SynchronizationType = downloadInfo.SynchronizationType;
                    newDownloadInfo.UpdatedState = downloadInfo.UpdatedState;
                    priorDownloadOperation = PriorDownloadOperation.RopSynchronizationGetTransferState;
                }
                else
                {
                    // Set the new Upload context value
                    newDownloadInfo.RelatedObjectHandleIndex = uploadInfo.RelatedObjectHandleIndex;
                    newDownloadInfo.SynchronizationType = uploadInfo.SynchronizationType;
                    newDownloadInfo.UpdatedState = uploadInfo.UpdatedState;
                }

                // Set the abstractFastTransferStreamType for new  Down loadContext value
                newDownloadInfo.AbstractFastTransferStreamType = FastTransferStreamType.state;
                newDownloadInfo.RelatedFastTransferOperation = EnumFastTransferOperation.SynchronizationGetTransferState;

                // Add new download context to DownloadContextContainer.
                changeConnection.DownloadContextContainer = changeConnection.DownloadContextContainer.Add(newDownloadInfo);
                connections[serverId] = changeConnection;
                result = RopResult.Success;

                // Because context created if the RopSynchronizationGetTransferState execute successful.
                ModelHelper.CaptureRequirement(
                    758,
                    @"[In RopSynchronizationGetTransferState ROP] The RopSynchronizationGetTransferState ROP ([MS-OXCROPS] section 2.2.13.8) creates a FastTransfer download context for the checkpoint ICS state of the operation identified by the given synchronization download context or synchronization upload context at the current moment in time.");
            }

            return result;
        }
        public static RopResult SynchronizationImportReadStateChanges(int serverId, int uploadContextHandleIndex, int messageHandleIndex, bool ireadstatus)
        {
            // The contractions conditions.
            Condition.IsTrue(connections.Count > 0);
            Condition.IsTrue(connections.Keys.Contains(serverId));
            Condition.IsTrue(connections[serverId].MessageContainer.Count > 0);

            // Initialize the return value.
            RopResult result = RopResult.InvalidParameter;
            ConnectionData changeConnection = connections[serverId];
            AbstractMessage currentMessage = new AbstractMessage();
            AbstractUploadInfo uploadInfo = new AbstractUploadInfo();

            // Identify whether the Message is existent or not and record the index.
            bool isCurrentMessageExist = false;
            int currentMessageindex = 0;

            // Identify whether the Upload information is existent or not and record the index.
            bool isCurrentUploadinfoExist = false;
            int currentUploadIndex = 0;

            foreach (AbstractUploadInfo tempUploadInfo in changeConnection.UploadContextContainer)
            {
                if (tempUploadInfo.UploadHandleIndex == uploadContextHandleIndex)
                {
                    // Set the value to the variable when the upload context is existent.
                    isCurrentUploadinfoExist = true;
                    uploadInfo = tempUploadInfo;
                    currentUploadIndex = changeConnection.UploadContextContainer.IndexOf(tempUploadInfo);
                }
            }

            foreach (AbstractMessage tempMessage in changeConnection.MessageContainer)
            {
                if (tempMessage.MessageHandleIndex == messageHandleIndex)
                {
                    // Set the value to the variable when the Message is existent.
                    isCurrentMessageExist = true;
                    currentMessage = tempMessage;
                    currentMessageindex = changeConnection.MessageContainer.IndexOf(tempMessage);
                }
            }

            if (isCurrentMessageExist)
            {
                // Find the parent folder of current message
                AbstractFolder parentfolder = new AbstractFolder();
                int parentfolderIndex = 0;
                foreach (AbstractFolder tempFolder in changeConnection.FolderContainer)
                {
                    if (tempFolder.FolderHandleIndex == currentMessage.FolderHandleIndex)
                    {
                        parentfolder = tempFolder;
                        parentfolderIndex = changeConnection.FolderContainer.IndexOf(tempFolder);
                        if (parentfolder.FolderPermission == PermissionLevels.None)
                        {
                            return result = RopResult.AccessDenied;
                        }
                    }
                }
            }

            if (isCurrentUploadinfoExist && isCurrentMessageExist)
            {
                // Set the message read status value.
                if (currentMessage.IsRead != ireadstatus)
                {
                    currentMessage.IsRead = ireadstatus;

                    // Get read State changeNumber.
                    currentMessage.ReadStateChangeNumberIndex = ModelHelper.GetChangeNumberIndex();

                    ModelHelper.CaptureRequirement(
                         2260,
                         @"[In Receiving a RopSynchronizationImportReadStateChanges Request]Upon successful completion of this ROP, the ICS state on the synchronization context MUST be updated by adding the new change number to the MetaTagCnsetRead property (section 2.2.1.1.4).");
                }

                // Record the related Synchronization Operation.
                uploadInfo.RelatedFastTransferOperation = EnumFastTransferOperation.SynchronizationReadStateChanges;

                // Update the upload context container and message container.
                changeConnection.UploadContextContainer = changeConnection.UploadContextContainer.Update(currentUploadIndex, uploadInfo);
                changeConnection.MessageContainer = changeConnection.MessageContainer.Update(currentMessageindex, currentMessage);
                connections[serverId] = changeConnection;
                result = RopResult.Success;

                ModelHelper.CaptureRequirement(
                        2449,
                        @"[In Uploading Changes Using ICS] Value is Success indicates No error occurred, or a conflict has been resolved.");

                // Because if the result is success means message read state changes is imported into the server replica.
                ModelHelper.CaptureRequirement(
                    905,
                    @"[In RopSynchronizationImportReadStateChanges ROP] The RopSynchronizationImportReadStateChanges ROP ([MS-OXCROPS] section 2.2.13.3) imports message read state changes into the server replica.");
            }

            return result;
        }
        public static RopResult SynchronizationImportMessageChange(int serverId, int uploadContextHandleIndex, int messageIdindex, ImportFlag importFlag, out int importMessageHandleIndex)
        {
            // The contractions conditions.
            Condition.IsTrue(connections.Count > 0);
            Condition.IsTrue(connections.Keys.Contains(serverId));
            Condition.IsTrue(connections[serverId].UploadContextContainer.Count > 0 && connections[serverId].LogonHandleIndex > 0);

            // Initialize the return value.
            RopResult result = RopResult.InvalidParameter;
            importMessageHandleIndex = -1;

            if ((importFlag & ImportFlag.InvalidParameter) == ImportFlag.InvalidParameter &&
                requirementContainer.ContainsKey(3509001) && requirementContainer[3509001])
            {
                result = RopResult.InvalidParameter;
                ModelHelper.CaptureRequirement(
                    3509001,
                    @"[In Appendix A: Product Behavior]  If unknown flags are set, implementation does fail the operation. <40> Section 3.2.5.9.4.2: Exchange 2010, Exchange 2013 and Exchange 2016 fail the ROP [RopSynchronizationImportMessageChange] if unknown bit flags are set.");

                return result;
            }
            else if ((importFlag & ImportFlag.InvalidParameter) == ImportFlag.InvalidParameter &&
                requirementContainer.ContainsKey(350900201) && requirementContainer[350900201])
            {
                result = RopResult.Success;
                ModelHelper.CaptureRequirement(
                    350900201,
                    @"[In Appendix A: Product Behavior]  If unknown flags are set, implementation does not fail the operation. <41> Section 3.2.5.9.4.2: Exchange 2007 do not fail the ROP [RopSynchronizationImportMessageChange] if unknown bit flags are set.");
            }

            // Get ConnectionData value.
            ConnectionData changeConnection = connections[serverId];
            AbstractUploadInfo uploadInfo = new AbstractUploadInfo();

            // Identify whether the current Upload information is existent or not.
            bool isCurrentUploadinfoExist = false;

            // Record current Upload information.
            int currentUploadIndex = 0;

            foreach (AbstractUploadInfo tempUploadInfo in changeConnection.UploadContextContainer)
            {
                if (tempUploadInfo.UploadHandleIndex == uploadContextHandleIndex)
                {
                    // Set the value to the  current upload context variable when the current upload context  is existent.
                    isCurrentUploadinfoExist = true;
                    uploadInfo = tempUploadInfo;
                    currentUploadIndex = changeConnection.UploadContextContainer.IndexOf(tempUploadInfo);
                }
            }

            if (isCurrentUploadinfoExist)
            {
                // Create a new Message
                AbstractMessage currentMessage = new AbstractMessage();

                // Identify whether the current message is existent or not.
                bool isMessageExist = false;

                // Record the current Message.
                int currentMessageIndex = 0;
                foreach (AbstractMessage tempMessage in changeConnection.MessageContainer)
                {
                    if (tempMessage.MessageIdIndex == messageIdindex)
                    {
                        // Set the value to the variable when the message is existent.
                        isMessageExist = true;
                        currentMessage = tempMessage;
                        currentMessageIndex = changeConnection.MessageContainer.IndexOf(tempMessage);
                    }
                }

                if (isMessageExist)
                {
                    // Set new change number
                    currentMessage.ChangeNumberIndex = ModelHelper.GetChangeNumberIndex();
                    ModelHelper.CaptureRequirement(1898, "[In Identifying Objects and Maintaining Change Numbers]A new change number is assigned to a messaging object each time it is modified.");

                    // Update the MessageContainer
                    changeConnection.MessageContainer = changeConnection.MessageContainer.Update(currentMessageIndex, currentMessage);
                }
                else
                {
                    // Set the new message handle 
                    currentMessage.MessageHandleIndex = AdapterHelper.GetHandleIndex();

                    // Set property value of abstract message object 
                    currentMessage.FolderHandleIndex = uploadInfo.RelatedObjectHandleIndex;
                    currentMessage.FolderIdIndex = uploadInfo.RelatedObjectIdIndex;
                    currentMessage.MessageProperties = new Sequence<string>();
                    currentMessage.IsRead = true;
                    if ((importFlag & ImportFlag.Normal) == ImportFlag.Normal)
                    {
                        currentMessage.IsFAImessage = false;
                    }

                    if ((importFlag & ImportFlag.Associated) == ImportFlag.Associated)
                    {
                        currentMessage.IsFAImessage = true;

                        // When the Associated is set and the message being imported is an FAI message this requirement is captured.
                        ModelHelper.CaptureRequirement(
                            813,
                            @"[In RopSynchronizationImportMessageChange ROP Request Buffer] [ImportFlag,when the name is Associated, the value is 0x10] If this flag is set, the message being imported is an FAI message.");
                    }
                    else
                    {
                        currentMessage.IsFAImessage = false;

                        // When the Associated is not set and the message being imported is a normal message this requirement is captured.
                        ModelHelper.CaptureRequirement(
                            814,
                            @"[In RopSynchronizationImportMessageChange ROP Request Buffer] [ImportFlag,when the name is Associated, the value is 0x10] If this flag is not set, the message being imported is a normal message.");
                    }

                    // Out the  new message handle
                    importMessageHandleIndex = currentMessage.MessageHandleIndex;

                    // Because this is out messageHandle so the OutputServerObject is a Message object.
                    ModelHelper.CaptureRequirement(805, "[In RopSynchronizationImportMessageChange ROP Response Buffer]OutputServerObject: The value of this field MUST be the Message object into which the client will upload the rest of the message changes.");
                    currentMessage.ChangeNumberIndex = ModelHelper.GetChangeNumberIndex();
                    ModelHelper.CaptureRequirement(1897, "[In Identifying Objects and Maintaining Change Numbers]When a new object is created, it is assigned a change number.");

                    // Add new Message to MessageContainer
                    changeConnection.MessageContainer = changeConnection.MessageContainer.Add(currentMessage);

                    // Record the related FastTransferOperation for Upload Information.
                    uploadInfo.RelatedFastTransferOperation = EnumFastTransferOperation.SynchronizationImportMessageChange;

                    // Update the UploadContextContainer.
                    changeConnection.UploadContextContainer = changeConnection.UploadContextContainer.Update(currentUploadIndex, uploadInfo);
                    connections[serverId] = changeConnection;

                    // Record RopSynchronizationImportMessageChange operation.
                    priorOperation = PriorOperation.RopSynchronizationImportMessageChange;
                    result = RopResult.Success;

                    ModelHelper.CaptureRequirement(
                    2449,
                    @"[In Uploading Changes Using ICS] Value is Success indicates No error occurred, or a conflict has been resolved.");

                    // Because if the result is success means the messages or changes are imported.
                    ModelHelper.CaptureRequirement(
                        782,
                        @"[In RopSynchronizationImportMessageChange ROP] The RopSynchronizationImportMessageChange ROP ([MS-OXCROPS] section 2.2.13.2) is used to import new messages or changes to existing messages into the server replica.");
                }
            }

            return result;
        }
        public static RopResult SynchronizationImportHierarchyChange(int serverId, int uploadContextHandleIndex, int parentFolderHandleIndex, Set<string> properties, int localFolderIdIndex, out int folderIdIndex)
        {
            // The contractions conditions.
            Condition.IsTrue(connections.Count > 0);
            Condition.IsTrue(connections.Keys.Contains(serverId));
            Condition.IsTrue(connections[serverId].UploadContextContainer.Count > 0);

            // Initialize the return value.
            RopResult result = RopResult.InvalidParameter;
            folderIdIndex = -1;

            if (parentFolderHandleIndex == -1)
            {
                result = RopResult.NoParentFolder;
                ModelHelper.CaptureRequirement(
                    2450,
                    @"[In Uploading Changes Using ICS] Value is NoParentFolder indicates An attempt is being made to upload a hierarchy change for a folder whose parent folder does not yet exist.");
            }
            else
            {
                // Get ConnectionData value.
                ConnectionData changeConnection = connections[serverId];

                // Record current Upload Information.
                AbstractUploadInfo currentUploadInfo = new AbstractUploadInfo();

                // Identify current Upload handle.
                bool isCurrentUploadHandleExist = false;

                foreach (AbstractUploadInfo tempUploadInfo in changeConnection.UploadContextContainer)
                {
                    if (tempUploadInfo.UploadHandleIndex == uploadContextHandleIndex)
                    {
                        // Set the value to the variable when the current upload context is existent.
                        isCurrentUploadHandleExist = true;
                        currentUploadInfo = tempUploadInfo;
                    }
                }

                if (isCurrentUploadHandleExist)
                {
                    // Initialize the variable
                    AbstractFolder parentfolder = new AbstractFolder();
                    bool isParentFolderExist = false;
                    int parentfolderIndex = 0;
                    AbstractFolder currentFolder = new AbstractFolder();
                    bool isFolderExist = false;
                    int currentFolderIndex = 0;

                    // Research the local folder Id.
                    foreach (AbstractFolder tempFolder in changeConnection.FolderContainer)
                    {
                        if (tempFolder.FolderIdIndex == localFolderIdIndex)
                        {
                            // Set the value to the  current Folder variable when the current folder  is existent.
                            isFolderExist = true;
                            currentFolder = tempFolder;
                            currentFolderIndex = changeConnection.FolderContainer.IndexOf(tempFolder);
                        }

                        if (tempFolder.FolderIdIndex == currentUploadInfo.RelatedObjectIdIndex)
                        {
                            // Set the value to the parent folder variable when the current parent folder is existent.
                            isParentFolderExist = true;
                            parentfolder = tempFolder;
                            parentfolderIndex = changeConnection.FolderContainer.IndexOf(tempFolder);
                        }
                    }

                    if (isFolderExist & isParentFolderExist)
                    {
                        foreach (string tempProperty in properties)
                        {
                            if (!currentFolder.FolderProperties.Contains(tempProperty))
                            {
                                // Add Property for folder
                                currentFolder.FolderProperties = currentFolder.FolderProperties.Add(tempProperty);
                            }
                        }

                        // Get the new change Number
                        currentFolder.ChangeNumberIndex = ModelHelper.GetChangeNumberIndex();

                        // Update the folder Container
                        changeConnection.FolderContainer = changeConnection.FolderContainer.Update(currentFolderIndex, currentFolder);
                    }
                    else
                    {
                        // Create a new folder
                        AbstractFolder newFolder = new AbstractFolder
                        {
                            FolderIdIndex = AdapterHelper.GetObjectIdIndex()
                        };

                        // Set new folder Id
                        folderIdIndex = newFolder.FolderIdIndex;

                        // Set value for new folder
                        newFolder.FolderProperties = properties;
                        newFolder.ParentFolderHandleIndex = parentfolder.FolderHandleIndex;
                        newFolder.ParentFolderIdIndex = parentfolder.FolderIdIndex;
                        newFolder.SubFolderIds = new Set<int>();
                        newFolder.MessageIds = new Set<int>();

                        // Add the new folder to parent folder
                        parentfolder.SubFolderIds = parentfolder.SubFolderIds.Add(newFolder.FolderIdIndex);
                        newFolder.FolderPermission = PermissionLevels.FolderOwner;
                        newFolder.ChangeNumberIndex = ModelHelper.GetChangeNumberIndex();
                        ModelHelper.CaptureRequirement(1897, "[In Identifying Objects and Maintaining Change Numbers]When a new object is created, it is assigned a change number.");

                        // Update FolderContainer information
                        changeConnection.FolderContainer = changeConnection.FolderContainer.Add(newFolder);
                        changeConnection.FolderContainer = changeConnection.FolderContainer.Update(parentfolderIndex, parentfolder);
                    }

                    // Return Success
                    connections[serverId] = changeConnection;

                    // Record RopSynchronizationImportHierarchyChange operation.
                    priorUploadOperation = PriorOperation.RopSynchronizationImportHierarchyChange;
                    result = RopResult.Success;

                    ModelHelper.CaptureRequirement(
                        2449,
                        @"[In Uploading Changes Using ICS] Value is Success indicates No error occurred, or a conflict has been resolved.");

                    // Because if the result is success means the folders or changes are imported.
                    ModelHelper.CaptureRequirement(
                        816,
                        @"[In RopSynchronizationImportHierarchyChange ROP] The RopSynchronizationImportHierarchyChange ROP ([MS-OXCROPS] section 2.2.13.4) is used to import new folders, or changes to existing folders, into the server replica.");
                }
            }

            return result;
        }
Example #10
0
        public static RopResult SynchronizationImportDeletes(int serverId, int uploadContextHandleIndex, Sequence<int> objIdIndexes, byte importDeleteFlag)
        {
            // The contractions conditions.
            Condition.IsTrue(connections.Count > 0);
            Condition.IsTrue(connections.Keys.Contains(serverId));
            Condition.IsTrue(connections[serverId].FolderContainer.Count > 0);
            if (requirementContainer.ContainsKey(90205002) && requirementContainer[90205002])
            {
                Condition.IsTrue(((ImportDeleteFlags)importDeleteFlag & ImportDeleteFlags.delete) == ImportDeleteFlags.delete);
            }

            // Initialize return value.
            RopResult result = RopResult.InvalidParameter;

            // When the ImportDeleteFlags flag is set HardDelete by Exchange 2007 then server return 0x80070057.
            if (importDeleteFlag == (byte)ImportDeleteFlags.HardDelete)
            {
                if (requirementContainer.ContainsKey(2593) && requirementContainer[2593])
                {
                    result = RopResult.NotSupported;
                    ModelHelper.CaptureRequirement(2593, "[In Appendix A: Product Behavior] <16> Section 2.2.3.2.4.5.1: The HardDelete flag is not supported by Exchange 2003 or Exchange 2007.");
                    return result;
                }
            }

            // When the ImportDeleteFlags flag is an invalid value (0x10) then server returns 0x80070057.
            if (importDeleteFlag == 0x10)
            {
                if (requirementContainer.ContainsKey(2254001) && requirementContainer[2254001])
                {
                    result = RopResult.NotSupported;
                }
                else
                {
                    result = RopResult.InvalidParameter;
                }

                return result;
            }

            // Get ConnectionData value.
            ConnectionData changeConnection = connections[serverId];

            // Create uploadInfo variable.
            AbstractUploadInfo uploadInfo = new AbstractUploadInfo();

            // Identify whether the Current Upload information is existent or not.
            bool isCurrentUploadinfoExist = false;

            // Record the current uploadInfo index.
            int currentUploadIndex = 0;
            foreach (AbstractUploadInfo tempUploadInfo in changeConnection.UploadContextContainer)
            {
                if (tempUploadInfo.UploadHandleIndex == uploadContextHandleIndex)
                {
                    // Set the value to the variable when the current upload context is existent.
                    isCurrentUploadinfoExist = true;
                    uploadInfo = tempUploadInfo;
                    currentUploadIndex = changeConnection.UploadContextContainer.IndexOf(tempUploadInfo);
                }
            }

            if (isCurrentUploadinfoExist)
            {
                // Set the upload information.
                uploadInfo.ImportDeleteflags = importDeleteFlag;
                AbstractFolder currentFolder = new AbstractFolder();

                // Record the current Folder Index
                int currentFolderIndex = 0;
                foreach (AbstractFolder tempFolder in changeConnection.FolderContainer)
                {
                    if (tempFolder.FolderHandleIndex == uploadInfo.RelatedObjectHandleIndex)
                    {
                        // Set the value to the variable when the current Folder is existent.
                        currentFolder = tempFolder;
                        currentFolderIndex = changeConnection.FolderContainer.IndexOf(tempFolder);
                    }
                }

                foreach (AbstractFolder tempFolder in changeConnection.FolderContainer)
                {
                    if ((tempFolder.ParentFolderIdIndex == currentFolder.FolderIdIndex) && objIdIndexes.Contains(tempFolder.FolderIdIndex))
                    {
                        // Remove current folder from FolderContainer and parent folder  when the parent Folder is existent.
                        changeConnection.FolderContainer = changeConnection.FolderContainer.Remove(tempFolder);
                        currentFolder.SubFolderIds = currentFolder.SubFolderIds.Remove(tempFolder.FolderIdIndex);
                    }

                    if (importDeleteFlag == (byte)ImportDeleteFlags.Hierarchy)
                    {
                        softDeleteFolderCount += 1;
                    }
                }

                foreach (AbstractMessage tempMessage in changeConnection.MessageContainer)
                {
                    if ((tempMessage.FolderIdIndex == currentFolder.FolderIdIndex) && objIdIndexes.Contains(tempMessage.MessageIdIndex))
                    {
                        // Remove current Message from MessageContainer and current folder when current Message is existent.
                        changeConnection.MessageContainer = changeConnection.MessageContainer.Remove(tempMessage);
                        currentFolder.MessageIds = currentFolder.MessageIds.Remove(tempMessage.MessageIdIndex);

                        if (importDeleteFlag == (byte)ImportDeleteFlags.delete)
                        {
                            softDeleteMessageCount += 1;
                        }
                    }
                }

                // Update the FolderContainer. 
                changeConnection.FolderContainer = changeConnection.FolderContainer.Update(currentFolderIndex, currentFolder);

                // Update the UploadContextContainer. 
                changeConnection.UploadContextContainer = changeConnection.UploadContextContainer.Update(currentUploadIndex, uploadInfo);
                connections[serverId] = changeConnection;

                result = RopResult.Success;

                ModelHelper.CaptureRequirement(
                    2449,
                    @"[In Uploading Changes Using ICS] Value is Success indicates No error occurred, or a conflict has been resolved.");

                // Because if the result is success means deletions of messages or folders into the server replica imported
                ModelHelper.CaptureRequirement(
                    884,
                    @"[In RopSynchronizationImportDeletes ROP] The RopSynchronizationImportDeletes ROP ([MS-OXCROPS] section 2.2.13.5) imports deletions of messages or folders into the server replica.");
                return result;
            }

            return result;
        }
Example #11
0
        public static RopResult SynchronizationOpenCollector(int serverId, int folderHandleIndex, SynchronizationTypes synchronizationType, out int uploadContextHandleIndex)
        {
            // The contractions conditions.
            Condition.IsTrue(connections.Count > 0);
            Condition.IsTrue(connections.Keys.Contains(serverId));
            Condition.IsTrue(connections[serverId].FolderContainer.Count > 0);

            // Initialize return value
            RopResult result = RopResult.InvalidParameter;
            uploadContextHandleIndex = -1;

            // Get ConnectionData value.
            ConnectionData changeConnection = connections[serverId];
            AbstractFolder currentfolder = new AbstractFolder();

            // Identify whether the CurrentFolder is existent or not.
            bool isCurrentFolderExist = false;

            // Identify whether the Current Folder is existent or not.
            foreach (AbstractFolder tempfolder in changeConnection.FolderContainer)
            {
                if (tempfolder.FolderHandleIndex == folderHandleIndex)
                {
                    // Set the value to the variable when the current folder is existent.
                    isCurrentFolderExist = true;
                    currentfolder = tempfolder;
                }
            }

            if (isCurrentFolderExist)
            {
                // Initialize the upload information.
                AbstractUploadInfo abstractUploadInfo = new AbstractUploadInfo
                {
                    UploadHandleIndex = AdapterHelper.GetHandleIndex()
                };
                uploadContextHandleIndex = abstractUploadInfo.UploadHandleIndex;
                ModelHelper.CaptureRequirement(778, "[In RopSynchronizationOpenCollector ROP Response Buffer]OutputServerObject: The value of this field MUST be the synchronization upload context.");
                abstractUploadInfo.SynchronizationType = synchronizationType;
                abstractUploadInfo.RelatedObjectHandleIndex = folderHandleIndex;
                abstractUploadInfo.RelatedObjectIdIndex = currentfolder.FolderIdIndex;

                // Initialize the updatedState information.
                abstractUploadInfo.UpdatedState.IdsetGiven = new Set<int>();
                abstractUploadInfo.UpdatedState.CnsetRead = new Set<int>();
                abstractUploadInfo.UpdatedState.CnsetSeen = new Set<int>();
                abstractUploadInfo.UpdatedState.CnsetSeenFAI = new Set<int>();

                // Add the  new value to UploadContextContainer.
                changeConnection.UploadContextContainer = changeConnection.UploadContextContainer.Add(abstractUploadInfo);

                connections[serverId] = changeConnection;

                // Record RopSynchronizationImportHierarchyChange operation.
                priorOperation = PriorOperation.RopSynchronizationOpenCollector;
                result = RopResult.Success;

                if (uploadContextHandleIndex != -1)
                {
                    // Because if uploadContextHandleIndex doesn't equal -1  and the ROP return success, so only if this ROP success and return a valid handler this requirement will be verified.
                    ModelHelper.CaptureRequirement(
                        769,
                        @"[In RopSynchronizationOpenCollector ROP] The RopSynchronizationOpenCollector ROP ([MS-OXCROPS] section 2.2.13.7) configures the synchronization upload operation and returns a handle to a synchronization upload context.");
                }
            }

            return result;
        }