/// <summary> /// Inserts the duplicate DICOM file into the <see cref="WorkQueue"/> for processing (if applicable). /// </summary> /// <param name="context">The processing context.</param> /// <param name="file">The duplicate DICOM file being processed.</param> /// <param name="data">Extra data to insert for the WorkQueue item.</param> /// <param name="sourceFilename">Optional source filename already saved to disk to import.</param> /// <returns>A <see cref="DicomProcessingResult"/> that contains the result of the processing.</returns> /// <remarks> /// This method inserts a <see cref="CommandBase"/> into <paramref name="context.CommandProcessor"/>. /// The outcome of the operation depends on the <see cref="DuplicateSopPolicyEnum"/> of the <see cref="ServerPartition"/>. /// If it is set to <see cref="DuplicateSopPolicyEnum.CompareDuplicates"/>, the duplicate file will be /// inserted into the <see cref="WorkQueue"/> for processing. /// </remarks> public static DicomProcessingResult Process(SopInstanceProcessorContext context, DicomMessageBase file, StudyProcessWorkQueueData data, string sourceFilename = null) { Platform.CheckForNullReference(file, "file"); Platform.CheckForNullReference(context, "context"); Platform.CheckMemberIsSet(context.Group, "parameters.Group"); Platform.CheckMemberIsSet(context.CommandProcessor, "parameters.CommandProcessor"); Platform.CheckMemberIsSet(context.StudyLocation, "parameters.StudyLocation"); if (string.IsNullOrEmpty(sourceFilename)) { Platform.CheckForNullReference(file as DicomFile, "file"); } var result = new DicomProcessingResult { DicomStatus = DicomStatuses.Success, Successful = true, StudyInstanceUid = file.DataSet[DicomTags.StudyInstanceUid].GetString(0, string.Empty), SeriesInstanceUid = file.DataSet[DicomTags.SeriesInstanceUid].GetString(0, string.Empty), SopInstanceUid = file.DataSet[DicomTags.SopInstanceUid].GetString(0, string.Empty), SopClassUid = file.DataSet[DicomTags.SopClassUid].GetString(0, string.Empty), AccessionNumber = file.DataSet[DicomTags.AccessionNumber].GetString(0, string.Empty) }; string failureMessage; if (context.DuplicateProcessing.HasValue && context.DuplicateProcessing.Value.Equals(DuplicateProcessingEnum.Reject)) { failureMessage = String.Format("Duplicate SOP Instance received, rejecting {0}", result.SopInstanceUid); Platform.Log(LogLevel.Info, failureMessage); result.SetError(DicomStatuses.DuplicateSOPInstance, failureMessage); return(result); } if (SopClassIsReport(result.SopClassUid) && context.StudyLocation.ServerPartition.AcceptLatestReport) { Platform.Log(LogLevel.Info, "Duplicate Report received, overwriting {0}", result.SopInstanceUid); if (string.IsNullOrEmpty(sourceFilename)) { ProcessStoredDuplicate(context, file as DicomFile, data, DuplicateProcessingEnum.OverwriteReport); } else { ProcessStoredDuplicateFile(context, sourceFilename, file, data, DuplicateProcessingEnum.OverwriteReport); } return(result); } if (DuplicatePolicy.IsParitionDuplicatePolicyOverridden(context.StudyLocation)) { // Note: this is a special case where we need to temporarily override the duplicate policy for a particular study // so that SIQ entry can be processed (#10569). This should only happen once in a blue moon. Platform.Log(LogLevel.Warn, "Duplicate instance received for study {0} on Partition {1}. Duplicate policy overridden in app config. Will overwrite {2}", result.StudyInstanceUid, context.StudyLocation.ServerPartition.AeTitle, result.SopInstanceUid); if (string.IsNullOrEmpty(sourceFilename)) { ProcessStoredDuplicate(context, file as DicomFile, data, DuplicateProcessingEnum.OverwriteSop); } else { ProcessStoredDuplicateFile(context, sourceFilename, file, data, DuplicateProcessingEnum.OverwriteSop); } return(result); } if (context.DuplicateProcessing.HasValue) { Platform.Log(LogLevel.Info, context.DuplicateProcessing.Value.Equals(DuplicateProcessingEnum.Compare) ? "Duplicate SOP Instance received, comparing {0}" : "Duplicate SOP Instance received, overwriting {0}", result.SopInstanceUid); if (string.IsNullOrEmpty(sourceFilename)) { ProcessStoredDuplicate(context, file as DicomFile, data, context.DuplicateProcessing.Value); } else { ProcessStoredDuplicateFile(context, sourceFilename, file, data, context.DuplicateProcessing.Value); } return(result); } if (context.StudyLocation.ServerPartition.DuplicateSopPolicyEnum.Equals(DuplicateSopPolicyEnum.AcceptLatest)) { Platform.Log(LogLevel.Info, "Duplicate SOP Instance received, overwriting {0}", result.SopInstanceUid); if (string.IsNullOrEmpty(sourceFilename)) { ProcessStoredDuplicate(context, file as DicomFile, data, DuplicateProcessingEnum.OverwriteSopAndUpdateDatabase); } else { ProcessStoredDuplicateFile(context, sourceFilename, file, data, DuplicateProcessingEnum.OverwriteSopAndUpdateDatabase); } return(result); } if (context.StudyLocation.ServerPartition.DuplicateSopPolicyEnum.Equals(DuplicateSopPolicyEnum.SendSuccess)) { Platform.Log(LogLevel.Info, "Duplicate SOP Instance received, sending success response {0}", result.SopInstanceUid); return(result); } if (context.StudyLocation.ServerPartition.DuplicateSopPolicyEnum.Equals(DuplicateSopPolicyEnum.RejectDuplicates)) { failureMessage = String.Format("Duplicate SOP Instance received, rejecting {0}", result.SopInstanceUid); Platform.Log(LogLevel.Info, failureMessage); result.SetError(DicomStatuses.DuplicateSOPInstance, failureMessage); return(result); } if (context.StudyLocation.ServerPartition.DuplicateSopPolicyEnum.Equals(DuplicateSopPolicyEnum.CompareDuplicates)) { if (string.IsNullOrEmpty(sourceFilename)) { ProcessStoredDuplicate(context, file as DicomFile, data, DuplicateProcessingEnum.Compare); } else { ProcessStoredDuplicateFile(context, sourceFilename, file, data, DuplicateProcessingEnum.Compare); } } else { failureMessage = String.Format("Duplicate SOP Instance received. Unsupported duplicate policy {0}.", context.StudyLocation.ServerPartition.DuplicateSopPolicyEnum); result.SetError(DicomStatuses.DuplicateSOPInstance, failureMessage); return(result); } return(result); }
private ProcessDuplicateResult ProcessDuplicate(DicomFile dupFile, WorkQueueUid uid, StudyXml studyXml) { var result = new ProcessDuplicateResult(); string duplicateSopPath = ServerPlatform.GetDuplicateUidPath(StorageLocation, uid); string basePath = StorageLocation.GetSopInstancePath(uid.SeriesInstanceUid, uid.SopInstanceUid); if (!File.Exists(basePath)) { // NOTE: This is special case. The file which caused dicom service to think this sop is a duplicate // no longer exists in the study folder. Perhaps it has been moved to another folder during auto reconciliation. // We have nothing to compare against so let's just throw it into the SIQ queue. CreateDuplicateSIQEntry(uid, dupFile, null); result.ActionTaken = DuplicateProcessResultAction.Reconcile; } else { // Check if system is configured to override the rule for this study if (DuplicatePolicy.IsParitionDuplicatePolicyOverridden(this.StorageLocation)) { return(OverwriteDuplicate(dupFile, uid, studyXml)); } else { var baseFile = new DicomFile(basePath); baseFile.Load(); if (DuplicateSopProcessorHelper.SopClassIsReport(dupFile.SopClass.Uid) && ServerPartition.AcceptLatestReport) { return(ProcessDuplicateReport(dupFile, baseFile, uid, studyXml)); } if (!dupFile.TransferSyntax.Equals(baseFile.TransferSyntax)) { // If they're compressed, and we have a codec, lets decompress and still do the comparison if (dupFile.TransferSyntax.Encapsulated && !dupFile.TransferSyntax.LossyCompressed && DicomCodecRegistry.GetCodec(dupFile.TransferSyntax) != null) { dupFile.ChangeTransferSyntax(TransferSyntax.ExplicitVrLittleEndian); } if (baseFile.TransferSyntax.Encapsulated && !baseFile.TransferSyntax.LossyCompressed && DicomCodecRegistry.GetCodec(baseFile.TransferSyntax) != null) { baseFile.ChangeTransferSyntax(TransferSyntax.ExplicitVrLittleEndian); } if (dupFile.TransferSyntax.Encapsulated || baseFile.TransferSyntax.Encapsulated) { string failure = String.Format("Base file transfer syntax is '{0}' while duplicate file has '{1}'", baseFile.TransferSyntax, dupFile.TransferSyntax); var list = new List <DicomAttributeComparisonResult>(); var compareResult = new DicomAttributeComparisonResult { ResultType = ComparisonResultType.DifferentValues, TagName = DicomTagDictionary.GetDicomTag(DicomTags.TransferSyntaxUid).Name, Details = failure }; list.Add(compareResult); CreateDuplicateSIQEntry(uid, dupFile, list); result.ActionTaken = DuplicateProcessResultAction.Reconcile; return(result); } } var failureReason = new List <DicomAttributeComparisonResult>(); if (baseFile.DataSet.Equals(dupFile.DataSet, ref failureReason)) { Platform.Log(LogLevel.Info, "Duplicate SOP being processed is identical. Removing SOP: {0}", baseFile.MediaStorageSopInstanceUid); RemoveWorkQueueUid(uid, duplicateSopPath); result.ActionTaken = DuplicateProcessResultAction.Delete; } else { CreateDuplicateSIQEntry(uid, dupFile, failureReason); result.ActionTaken = DuplicateProcessResultAction.Reconcile; } } } return(result); }
// TODO: Make these values configurable #endregion #region Public Methods /// <summary> /// Inserts the duplicate DICOM file into the <see cref="WorkQueue"/> for processing (if applicable). /// </summary> /// <param name="context">The processing context.</param> /// <param name="file">Thje duplicate DICOM file being processed.</param> /// <returns>A <see cref="DicomProcessingResult"/> that contains the result of the processing.</returns> /// <remarks> /// This method inserts <see cref="ServerCommand"/> into <paramref name="context.CommandProcessor"/>. /// The outcome of the operation depends on the <see cref="DuplicateSopPolicyEnum"/> of the <see cref="ServerPartition"/>. /// If it is set to <see cref="DuplicateSopPolicyEnum.CompareDuplicates"/>, the duplicate file will be /// inserted into the <see cref="WorkQueue"/> for processing. /// </remarks> static public DicomProcessingResult Process(SopProcessingContext context, DicomFile file) { Platform.CheckForNullReference(file, "file"); Platform.CheckForNullReference(context, "context"); Platform.CheckMemberIsSet(context.Group, "parameters.Group"); Platform.CheckMemberIsSet(context.CommandProcessor, "parameters.CommandProcessor"); Platform.CheckMemberIsSet(context.StudyLocation, "parameters.StudyLocation"); var result = new DicomProcessingResult { DicomStatus = DicomStatuses.Success, Successful = true, StudyInstanceUid = file.DataSet[DicomTags.StudyInstanceUid].GetString(0, string.Empty), SeriesInstanceUid = file.DataSet[DicomTags.SeriesInstanceUid].GetString(0, string.Empty), SopInstanceUid = file.DataSet[DicomTags.SopInstanceUid].GetString(0, string.Empty), SopClassUid = file.DataSet[DicomTags.SopClassUid].GetString(0, string.Empty), AccessionNumber = file.DataSet[DicomTags.AccessionNumber].GetString(0, string.Empty) }; string failureMessage; if (SopClassIsReport(result.SopClassUid) && context.StudyLocation.ServerPartition.AcceptLatestReport) { Platform.Log(LogLevel.Info, "Duplicate Report received, overwriting {0}", result.SopInstanceUid); SaveDuplicate(context, file); context.CommandProcessor.AddCommand( new UpdateWorkQueueCommand(file, context.StudyLocation, true, ServerPlatform.DuplicateFileExtension, context.Group)); return(result); } if (DuplicatePolicy.IsParitionDuplicatePolicyOverridden(context.StudyLocation)) { Platform.Log(LogLevel.Warn, "Duplicate instance received for study {0} on Partition {1}. Duplicate policy overridden. Will overwrite {2}", result.StudyInstanceUid, context.StudyLocation.ServerPartition.AeTitle, result.SopInstanceUid); SaveDuplicate(context, file); context.CommandProcessor.AddCommand(new UpdateWorkQueueCommand(file, context.StudyLocation, true, ServerPlatform.DuplicateFileExtension, context.Group)); return(result); } else { if (context.StudyLocation.ServerPartition.DuplicateSopPolicyEnum.Equals(DuplicateSopPolicyEnum.SendSuccess)) { Platform.Log(LogLevel.Info, "Duplicate SOP Instance received, sending success response {0}", result.SopInstanceUid); return(result); } if (context.StudyLocation.ServerPartition.DuplicateSopPolicyEnum.Equals(DuplicateSopPolicyEnum.RejectDuplicates)) { failureMessage = String.Format("Duplicate SOP Instance received, rejecting {0}", result.SopInstanceUid); Platform.Log(LogLevel.Info, failureMessage); result.SetError(DicomStatuses.DuplicateSOPInstance, failureMessage); return(result); } if (context.StudyLocation.ServerPartition.DuplicateSopPolicyEnum.Equals(DuplicateSopPolicyEnum.CompareDuplicates)) { SaveDuplicate(context, file); context.CommandProcessor.AddCommand( new UpdateWorkQueueCommand(file, context.StudyLocation, true, ServerPlatform.DuplicateFileExtension, context.Group)); } else { failureMessage = String.Format("Duplicate SOP Instance received. Unsupported duplicate policy {0}.", context.StudyLocation.ServerPartition.DuplicateSopPolicyEnum); result.SetError(DicomStatuses.DuplicateSOPInstance, failureMessage); return(result); } } return(result); }