/// <summary>
        /// Reprocess a specific study.
        /// </summary>
        /// <param name="partition">The ServerPartition the study is on.</param>
        /// <param name="location">The storage location of the study to process.</param>
        /// <param name="engine">The rules engine to use when processing the study.</param>
        /// <param name="postArchivalEngine">The rules engine used for studies that have been archived.</param>
        /// <param name="dataAccessEngine">The rules engine strictly used for setting data acess.</param>
        private static void ProcessStudy(ServerPartition partition, StudyStorageLocation location, ServerRulesEngine engine, ServerRulesEngine postArchivalEngine, ServerRulesEngine dataAccessEngine)
        {
            if (!location.QueueStudyStateEnum.Equals(QueueStudyStateEnum.Idle) || !location.AcquireWriteLock())
            {
                Platform.Log(LogLevel.Error, "Unable to lock study {0}. The study is being processed. (Queue State: {1})", location.StudyInstanceUid, location.QueueStudyStateEnum.Description);
            }
            else
            {
                try
                {
                    DicomFile msg = LoadInstance(location);
                    if (msg == null)
                    {
                        Platform.Log(LogLevel.Error, "Unable to load file for study {0}", location.StudyInstanceUid);
                        return;
                    }

                    bool archiveQueueExists;
                    bool archiveStudyStorageExists;
                    bool filesystemDeleteExists;
                    using (IReadContext read = PersistentStoreRegistry.GetDefaultStore().OpenReadContext())
                    {
                        // Check for existing archive queue entries
                        var archiveQueueBroker   = read.GetBroker <IArchiveQueueEntityBroker>();
                        var archiveQueueCriteria = new ArchiveQueueSelectCriteria();
                        archiveQueueCriteria.StudyStorageKey.EqualTo(location.Key);
                        archiveQueueExists = archiveQueueBroker.Count(archiveQueueCriteria) > 0;


                        var archiveStorageBroker        = read.GetBroker <IArchiveStudyStorageEntityBroker>();
                        var archiveStudyStorageCriteria = new ArchiveStudyStorageSelectCriteria();
                        archiveStudyStorageCriteria.StudyStorageKey.EqualTo(location.Key);
                        archiveStudyStorageExists = archiveStorageBroker.Count(archiveStudyStorageCriteria) > 0;

                        var filesystemQueueBroker   = read.GetBroker <IFilesystemQueueEntityBroker>();
                        var filesystemQueueCriteria = new FilesystemQueueSelectCriteria();
                        filesystemQueueCriteria.StudyStorageKey.EqualTo(location.Key);
                        filesystemQueueCriteria.FilesystemQueueTypeEnum.EqualTo(FilesystemQueueTypeEnum.DeleteStudy);
                        filesystemDeleteExists = filesystemQueueBroker.Count(filesystemQueueCriteria) > 0;
                    }

                    var context = new ServerActionContext(msg, location.FilesystemKey, partition, location.Key);
                    using (context.CommandProcessor = new ServerCommandProcessor("Study Rule Processor"))
                    {
                        // Check if the Study has been archived
                        if (archiveStudyStorageExists && !archiveQueueExists && !filesystemDeleteExists)
                        {
                            // Add a command to delete the current filesystemQueue entries, so that they can
                            // be reinserted by the rules engine.
                            context.CommandProcessor.AddCommand(new DeleteFilesystemQueueCommand(location.Key, ServerRuleApplyTimeEnum.StudyArchived));

                            // How to deal with exiting FilesystemQueue entries is problematic here.  If the study
                            // has been migrated off tier 1, we probably don't want to modify the tier migration
                            // entries.  Compression entries may have been entered when the Study was initially
                            // processed, we don't want to delete them, because they might still be valid.
                            // We just re-run the rules engine at this point, and delete only the StudyPurge entries,
                            // since those we know at least would only be applied for archived studies.
                            postArchivalEngine.Execute(context);

                            // Post Archive doesn't allow data access rules.  Force Data Access rules to be reapplied
                            // to these studies also.
                            dataAccessEngine.Execute(context);
                        }
                        else
                        {
                            // Add a command to delete the current filesystemQueue entries, so that they can
                            // be reinserted by the rules engine.
                            context.CommandProcessor.AddCommand(new DeleteFilesystemQueueCommand(location.Key, ServerRuleApplyTimeEnum.StudyProcessed));

                            // Execute the rules engine, insert commands to update the database into the command processor.
                            engine.Execute(context);

                            // Re-do insert into the archive queue.
                            // Note: the stored procedure will update the archive entry if it already exists
                            context.CommandProcessor.AddCommand(
                                new InsertArchiveQueueCommand(location.ServerPartitionKey, location.Key));
                        }

                        // Do the actual database updates.
                        if (false == context.CommandProcessor.Execute())
                        {
                            Platform.Log(LogLevel.Error, "Unexpected failure processing Study level rules for study {0}", location.StudyInstanceUid);
                        }

                        // Log the FilesystemQueue related entries
                        location.LogFilesystemQueue();
                    }
                }
                finally
                {
                    location.ReleaseWriteLock();
                }
            }
        }