public async Task GivenExistingExtendedQueryTagandTagError_WhenDeleteExtendedQueryTag_ThenTagErrorShouldAlsoBeRemoved()
        {
            string studyInstanceUid  = TestUidGenerator.Generate();
            string seriesInstanceUid = TestUidGenerator.Generate();
            string sopInstanceUid    = TestUidGenerator.Generate();

            DicomTag tag       = DicomTag.DeviceSerialNumber;
            long     watermark = await AddInstanceAsync(studyInstanceUid, seriesInstanceUid, sopInstanceUid);

            int tagKey = await AddTagAsync(tag);

            ValidationErrorCode errorCode = ValidationErrorCode.InvalidCharacters;
            await _extendedQueryTagErrorStore.AddExtendedQueryTagErrorAsync(tagKey, errorCode, watermark);

            var extendedQueryTagErrorBeforeTagDeletion = await _extendedQueryTagErrorStore.GetExtendedQueryTagErrorsAsync(tag.GetPath(), int.MaxValue, 0);

            Assert.Equal(1, extendedQueryTagErrorBeforeTagDeletion.Count);

            var extendedQueryTagBeforeTagDeletion = await _extendedQueryTagStore.GetExtendedQueryTagAsync(tag.GetPath());

            await _extendedQueryTagStore.DeleteExtendedQueryTagAsync(tag.GetPath(), tag.GetDefaultVR().Code);

            await Assert.ThrowsAsync <ExtendedQueryTagNotFoundException>(
                () => _extendedQueryTagStore.GetExtendedQueryTagAsync(tag.GetPath()));

            await Assert.ThrowsAsync <ExtendedQueryTagNotFoundException>(
                () => _extendedQueryTagErrorStore.GetExtendedQueryTagErrorsAsync(tag.GetPath(), 1, 0));

            Assert.False(await _errorStoreTestHelper.DoesExtendedQueryTagErrorExistAsync(tagKey));
        }
        private static void ValidateVRCode(DicomTag tag, string vrCode, string tagPath)
        {
            DicomVR dicomVR = string.IsNullOrWhiteSpace(vrCode) ? null : ParseVRCode(vrCode, tagPath);

            if (tag.DictionaryEntry != DicomDictionary.UnknownTag)
            {
                // if VR is specified for knownTag, validate
                if (dicomVR != null)
                {
                    if (!tag.DictionaryEntry.ValueRepresentations.Contains(dicomVR))
                    {
                        // not a valid VR
                        throw new ExtendedQueryTagEntryValidationException(
                                  string.Format(CultureInfo.InvariantCulture, DicomCoreResource.UnsupportedVRCodeOnTag, vrCode, tagPath, tag.GetDefaultVR()));
                    }
                }
                else
                {
                    // otherwise, get default one
                    dicomVR = tag.GetDefaultVR();
                }
            }
            else
            {
                // for unknown tag, vrCode is required
                if (dicomVR == null)
                {
                    throw new ExtendedQueryTagEntryValidationException(
                              string.Format(CultureInfo.InvariantCulture, DicomCoreResource.MissingVRCode, tagPath));
                }
            }

            EnsureVRIsSupported(dicomVR, tagPath);
        }
        public async Task GivenTags_WhenDeleteTag_ThenAssociatedErrorsShouldBeRemoved()
        {
            string studyUid    = TestUidGenerator.Generate();
            string seriesUid   = TestUidGenerator.Generate();
            string instanceUid = TestUidGenerator.Generate();

            // add instances
            long watermark = await AddInstanceAsync(studyUid, seriesUid, instanceUid);

            // add tag
            DicomTag tag1    = DicomTag.DeviceSerialNumber;
            int      tagKey1 = await AddTagAsync(tag1);

            DicomTag tag2    = DicomTag.DeviceID;
            int      tagKey2 = await AddTagAsync(tag2);

            // add errors
            ValidationErrorCode errorCode = ValidationErrorCode.DateIsInvalid;
            // add error on instance for both tag
            await _extendedQueryTagErrorStore.AddExtendedQueryTagErrorAsync(tagKey1, errorCode, watermark);

            await _extendedQueryTagErrorStore.AddExtendedQueryTagErrorAsync(tagKey2, errorCode, watermark);

            // delete tag
            await _extendedQueryTagStore.DeleteExtendedQueryTagAsync(tag1.GetPath(), tag1.GetDefaultVR().Code);

            // check errors
            Assert.False(await _errorStoreTestHelper.DoesExtendedQueryTagErrorExistAsync(tagKey1));
            Assert.True(await _errorStoreTestHelper.DoesExtendedQueryTagErrorExistAsync(tagKey2));
        }
Example #4
0
        /// <summary>
        /// Normalize custom tag entry before saving to CustomTagStore.
        /// </summary>
        /// <param name="customTagEntry">The custom tag entry.</param>
        /// <returns>Normalize custom tag entry.</returns>
        public static CustomTagEntry Normalize(this CustomTagEntry customTagEntry)
        {
            DicomTagParser dicomTagParser = new DicomTagParser();

            DicomTag[] tags;
            if (!dicomTagParser.TryParse(customTagEntry.Path, out tags, supportMultiple: false))
            {
                // not a valid dicom tag path
                throw new CustomTagEntryValidationException(
                          string.Format(CultureInfo.InvariantCulture, DicomCoreResource.InvalidCustomTag, customTagEntry));
            }

            DicomTag tag  = tags[0];
            string   path = tag.GetPath();
            string   vr   = customTagEntry.VR;

            // when VR is not specified for standard tag,
            if (!tag.IsPrivate && tag.DictionaryEntry != DicomDictionary.UnknownTag)
            {
                if (string.IsNullOrWhiteSpace(vr))
                {
                    vr = tag.GetDefaultVR()?.Code;
                }
            }

            vr = vr.ToUpperInvariant();

            return(new CustomTagEntry(path, vr, customTagEntry.Level, customTagEntry.Status));
        }
Example #5
0
        public void GivenVROfLowerCase_WhenFormalizing_ThenVRShouldBeUpperCase()
        {
            DicomTag       tag        = DicomTag.DeviceLabel;
            CustomTagEntry entry      = new CustomTagEntry(tag.GetPath(), tag.GetDefaultVR().Code.ToLowerInvariant(), CustomTagLevel.Instance, CustomTagStatus.Added);
            CustomTagEntry normalized = entry.Normalize();

            Assert.Equal(entry.VR.ToUpperInvariant(), normalized.VR);
        }
Example #6
0
        public void GivenStandardTagWithoutVR_WhenNormalizing_ThenVRShouldBeFilled(string vr)
        {
            DicomTag tag = DicomTag.DeviceSerialNumber;
            AddExtendedQueryTagEntry entry      = CreateExtendedQueryTagEntry(tag.GetPath(), vr, null, QueryTagLevel.Instance);
            AddExtendedQueryTagEntry normalized = entry.Normalize();

            Assert.Equal(tag.GetDefaultVR().Code, normalized.VR);
        }
Example #7
0
        public void GivenStandardTagWithoutVR_WhenFormalizing_ThenVRShouldBeFilled(string vr)
        {
            DicomTag       tag        = DicomTag.DeviceSerialNumber;
            CustomTagEntry entry      = new CustomTagEntry(tag.GetPath(), vr, CustomTagLevel.Instance, CustomTagStatus.Added);
            CustomTagEntry normalized = entry.Normalize();

            Assert.Equal(tag.GetDefaultVR().Code, normalized.VR);
        }
Example #8
0
        /// <summary>
        /// Initializes a new instance of the <see cref="QueryTag"/> class.
        /// </summary>
        /// <remarks>Used for constuctoring from core dicom tag.PatientName e.g. </remarks>
        /// <param name="tag">The core dicom Tag.</param>
        public QueryTag(DicomTag tag)
        {
            EnsureArg.IsNotNull(tag, nameof(tag));

            Tag   = tag;
            VR    = tag.GetDefaultVR();
            Level = QueryLimit.GetQueryTagLevel(tag);
            ExtendedQueryTagStoreEntry = null;
        }
        /// <summary>
        /// Validate custom tag entry.
        /// </summary>
        /// <param name="tagEntry">the tag entry.</param>
        private void ValidateCustomTagEntry(CustomTagEntry tagEntry)
        {
            DicomTag tag = ParseTag(tagEntry.Path);

            // cannot be any tag we already support
            if (QueryLimit.AllInstancesTags.Contains(tag))
            {
                throw new CustomTagEntryValidationException(
                          string.Format(CultureInfo.InvariantCulture, DicomCoreResource.CustomTagAlreadyExists, tag.DictionaryEntry.Name));
            }

            if (tag.IsPrivate)
            {
                // this is private tag, VR is required
                ParseVRCode(tagEntry.VR);
                EnsureVRIsSupported(tagEntry.VR);
            }
            else
            {
                // stardard tag must have name - should not be "Unknown".
                if (tag.DictionaryEntry.Equals(DicomDictionary.UnknownTag))
                {
                    // not a valid dicom tag
                    throw new CustomTagEntryValidationException(
                              string.Format(CultureInfo.InvariantCulture, DicomCoreResource.InvalidCustomTag, tag));
                }

                if (string.IsNullOrWhiteSpace(tagEntry.VR))
                {
                    // When VR is missing for standard tag, still need to verify VRCode
                    string vrCode = tag.GetDefaultVR()?.Code;

                    EnsureVRIsSupported(vrCode);
                }
                else
                {
                    // when VR is specified, verify it's correct
                    // parse VR
                    DicomVR vr = ParseVRCode(tagEntry.VR);

                    EnsureVRIsSupported(vr.Code);

                    if (!tag.DictionaryEntry.ValueRepresentations.Contains(vr))
                    {
                        // not a valid VR
                        throw new CustomTagEntryValidationException(
                                  string.Format(CultureInfo.InvariantCulture, DicomCoreResource.UnsupportedVRCodeOnTag, vr.Code, tag));
                    }
                }
            }
        }
        public void GivenDisabledTag_WhenParse_ThenShouldThrowException()
        {
            DicomTag tag1 = DicomTag.PatientAge;

            QueryTag[] tags = new QueryTag[]
            {
                new QueryTag(new ExtendedQueryTagStoreEntry(1, tag1.GetPath(), tag1.GetDefaultVR().Code, null, QueryTagLevel.Instance, ExtendedQueryTagStatus.Ready, QueryStatus.Disabled, 1)), // disabled
            };
            var parameters = CreateParameters(
                new Dictionary <string, string>
            {
                { tag1.GetFriendlyName(), "CoronaPatient" },
            },
                QueryResource.AllInstances);

            var exp = Assert.Throws <QueryParseException>(() => _queryParser.Parse(parameters, tags));

            Assert.Equal($"Query is disabled on specified attribute '{tag1.GetFriendlyName()}'.", exp.Message);
        }
        public void GivenErroneousTag_WhenParse_ThenShouldBeInList()
        {
            DicomTag tag1 = DicomTag.PatientAge;
            DicomTag tag2 = DicomTag.PatientAddress;

            QueryTag[] tags = new QueryTag[]
            {
                new QueryTag(new ExtendedQueryTagStoreEntry(1, tag1.GetPath(), tag1.GetDefaultVR().Code, null, QueryTagLevel.Instance, ExtendedQueryTagStatus.Ready, QueryStatus.Enabled, 1)), // has error
                new QueryTag(new ExtendedQueryTagStoreEntry(2, tag2.GetPath(), tag2.GetDefaultVR().Code, null, QueryTagLevel.Instance, ExtendedQueryTagStatus.Ready, QueryStatus.Enabled, 0)), // no error
            };
            QueryExpression queryExpression = _queryParser.Parse(
                CreateParameters(
                    new Dictionary <string, string>
            {
                { tag1.GetFriendlyName(), "CoronaPatient" },
                { tag2.GetPath(), "20200403" },
            },
                    QueryResource.AllInstances),
                tags);

            Assert.Single(queryExpression.ErroneousTags);
            Assert.Equal(queryExpression.ErroneousTags.First(), tag1.GetFriendlyName());
        }
        /// <summary>
        /// Normalize extended query tag entry before saving to ExtendedQueryTagStore.
        /// </summary>
        /// <param name="extendedQueryTagEntry">The extended query tag entry.</param>
        /// <returns>Normalize extended query tag entry.</returns>
        public static AddExtendedQueryTagEntry Normalize(this AddExtendedQueryTagEntry extendedQueryTagEntry)
        {
            DicomTagParser dicomTagParser = new DicomTagParser();

            DicomTag[] tags;
            if (!dicomTagParser.TryParse(extendedQueryTagEntry.Path, out tags, supportMultiple: false))
            {
                // not a valid dicom tag path
                throw new ExtendedQueryTagEntryValidationException(
                          string.Format(CultureInfo.InvariantCulture, DicomCoreResource.InvalidExtendedQueryTag, extendedQueryTagEntry));
            }

            DicomTag tag            = tags[0];
            string   path           = tag.GetPath();
            string   vr             = extendedQueryTagEntry.VR;
            string   privateCreator = string.IsNullOrWhiteSpace(extendedQueryTagEntry.PrivateCreator) ? null : extendedQueryTagEntry.PrivateCreator;

            // when VR is not specified for known tags
            if (tag.DictionaryEntry != DicomDictionary.UnknownTag)
            {
                if (string.IsNullOrWhiteSpace(vr))
                {
                    vr = tag.GetDefaultVR()?.Code;
                }
            }

            vr = vr?.ToUpperInvariant();

            return(new AddExtendedQueryTagEntry()
            {
                Path = path,
                VR = vr,
                PrivateCreator = privateCreator,
                Level = extendedQueryTagEntry.Level,
            });
        }
Example #13
0
        public async Task GivenValidExtendedQueryTags_WhenGoThroughEndToEndScenario_ThenShouldSucceed()
        {
            // Prepare 3 extended query tags.
            // One is private tag on Instance level
            // To add private tag, need to add identification code element at first.
            DicomTag identificationCodeTag = new DicomTag(0x0407, 0x0010);

            DicomElement identificationCodeElement = new DicomLongString(identificationCodeTag, PrivateCreatorName);

            DicomTag privateTag = new DicomTag(0x0407, 0x1001, PrivateCreatorName);
            AddExtendedQueryTagEntry privateQueryTag = new AddExtendedQueryTagEntry {
                Path = privateTag.GetPath(), VR = DicomVRCode.SS, Level = QueryTagLevel.Instance, PrivateCreator = privateTag.PrivateCreator.Creator
            };

            // One is standard tag on Series level
            DicomTag standardTagSeries = DicomTag.ManufacturerModelName;
            AddExtendedQueryTagEntry standardTagSeriesQueryTag = new AddExtendedQueryTagEntry {
                Path = standardTagSeries.GetPath(), VR = standardTagSeries.GetDefaultVR().Code, Level = QueryTagLevel.Series
            };

            // One is standard tag on Study level
            DicomTag standardTagStudy = DicomTag.PatientSex;
            AddExtendedQueryTagEntry standardTagStudyQueryTag = new AddExtendedQueryTagEntry {
                Path = standardTagStudy.GetPath(), VR = standardTagStudy.GetDefaultVR().Code, Level = QueryTagLevel.Study
            };

            AddExtendedQueryTagEntry[] queryTags = new AddExtendedQueryTagEntry[] { privateQueryTag, standardTagSeriesQueryTag, standardTagStudyQueryTag };

            // Create 3 test files on same studyUid.
            string studyUid     = TestUidGenerator.Generate();
            string seriesUid1   = TestUidGenerator.Generate();
            string seriesUid2   = TestUidGenerator.Generate();
            string instanceUid1 = TestUidGenerator.Generate();
            string instanceUid2 = TestUidGenerator.Generate();
            string instanceUid3 = TestUidGenerator.Generate();

            // One is on seriesUid1 and instanceUid1
            DicomDataset dataset1 = Samples.CreateRandomInstanceDataset(studyInstanceUid: studyUid, seriesInstanceUid: seriesUid1, sopInstanceUid: instanceUid1);

            dataset1.Add(identificationCodeElement);
            dataset1.AddOrUpdate(new DicomSignedShort(privateTag, 1));
            dataset1.Add(standardTagSeries, "ManufacturerModelName1");
            dataset1.Add(standardTagStudy, "0");

            // One is on seriesUid1 and instanceUid2
            DicomDataset dataset2 = Samples.CreateRandomInstanceDataset(studyInstanceUid: studyUid, seriesInstanceUid: seriesUid1, sopInstanceUid: instanceUid2);

            dataset2.Add(identificationCodeElement);
            dataset2.AddOrUpdate(new DicomSignedShort(privateTag, 2));
            dataset2.Add(standardTagSeries, "ManufacturerModelName2");
            dataset2.Add(standardTagStudy, "0");

            // One is on seriesUid2 and instanceUid3
            DicomDataset dataset3 = Samples.CreateRandomInstanceDataset(studyInstanceUid: studyUid, seriesInstanceUid: seriesUid2, sopInstanceUid: instanceUid3);

            dataset3.Add(identificationCodeElement);
            dataset3.AddOrUpdate(new DicomSignedShort(privateTag, 3));
            dataset3.Add(standardTagSeries, "ManufacturerModelName3");
            dataset3.Add(standardTagStudy, "1");
            try
            {
                // Add extended query tags

                await _client.AddExtendedQueryTagAsync(queryTags);

                try
                {
                    foreach (var queryTag in queryTags)
                    {
                        GetExtendedQueryTagEntry returnTag = await(await _client.GetExtendedQueryTagAsync(queryTag.Path)).GetValueAsync();
                        CompareExtendedQueryTagEntries(queryTag, returnTag);
                    }

                    // Upload test files
                    IEnumerable <DicomFile> dicomFiles = new DicomDataset[] { dataset1, dataset2, dataset3 }.Select(dataset => new DicomFile(dataset));

                    await _client.StoreAsync(dicomFiles, studyInstanceUid : string.Empty, cancellationToken : default);

                    // Query on instance for private tag
                    DicomWebAsyncEnumerableResponse <DicomDataset> queryInstanceResponse = await _client.QueryAsync(new Uri($"/instances?{privateTag.GetPath()}=3", UriKind.Relative), cancellationToken : default);

                    DicomDataset[] instanceResult = await queryInstanceResponse.ToArrayAsync();

                    Assert.Single(instanceResult);
                    Assert.Equal(instanceUid3, instanceResult[0].GetSingleValue <string>(DicomTag.SOPInstanceUID));

                    // Query on series for standardTagSeries
                    DicomWebAsyncEnumerableResponse <DicomDataset> querySeriesResponse = await _client.QueryAsync(new Uri($"/series?{standardTagSeries.GetPath()}=ManufacturerModelName2", UriKind.Relative), cancellationToken : default);

                    DicomDataset[] seriesResult = await querySeriesResponse.ToArrayAsync();

                    Assert.Single(seriesResult);
                    Assert.Equal(seriesUid1, seriesResult[0].GetSingleValue <string>(DicomTag.SeriesInstanceUID));

                    // Query on study for standardTagStudy
                    DicomWebAsyncEnumerableResponse <DicomDataset> queryStudyResponse = await _client.QueryAsync(new Uri($"/studies?{standardTagStudy.GetPath()}=1", UriKind.Relative), cancellationToken : default);

                    DicomDataset[] studyResult = await queryStudyResponse.ToArrayAsync();

                    Assert.Single(studyResult);
                    Assert.Equal(studyUid, seriesResult[0].GetSingleValue <string>(DicomTag.StudyInstanceUID));
                }
                finally
                {
                    await _client.DeleteStudyAsync(studyUid);
                }
            }
            finally
            {
                // Cleanup extended query tags, also verify GetExtendedQueryTagsAsync.
                var responseQueryTags = await(await _client.GetExtendedQueryTagsAsync()).GetValueAsync();
                foreach (var rTag in responseQueryTags)
                {
                    if (queryTags.Any(tag => tag.Path == rTag.Path))
                    {
                        await _client.DeleteExtendedQueryTagAsync(rTag.Path);
                    }
                }
            }
        }
Example #14
0
 public static ExtendedQueryTagStoreEntry BuildExtendedQueryTagStoreEntry(this DicomTag tag, int key = 1, string vr = null, string privateCreator = null, QueryTagLevel level = QueryTagLevel.Series, ExtendedQueryTagStatus status = ExtendedQueryTagStatus.Ready)
 {
     return(new ExtendedQueryTagStoreEntry(key: key, path: tag.GetPath(), vr: vr ?? tag.GetDefaultVR().Code, privateCreator: privateCreator, level: level, status: status));
 }
        public async Task GivenExtendedQueryTag_WhenReindexing_ThenShouldSucceed()
        {
            DicomTag weightTag = DicomTag.PatientWeight;
            DicomTag sizeTag   = DicomTag.PatientSize;

            // Try to delete these extended query tags.
            await CleanupExtendedQueryTag(weightTag);
            await CleanupExtendedQueryTag(sizeTag);

            // Define DICOM files
            DicomDataset instance1 = Samples.CreateRandomInstanceDataset();

            instance1.Add(weightTag, 68.0M);
            instance1.Add(sizeTag, 1.78M);

            DicomDataset instance2 = Samples.CreateRandomInstanceDataset();

            instance2.Add(weightTag, 50.0M);
            instance2.Add(sizeTag, 1.5M);

            // Upload files
            Assert.True((await _instanceManager.StoreAsync(new DicomFile(instance1))).IsSuccessStatusCode);
            Assert.True((await _instanceManager.StoreAsync(new DicomFile(instance2))).IsSuccessStatusCode);

            // Add extended query tag
            OperationStatus operation = await _tagManager.AddTagsAsync(
                new AddExtendedQueryTagEntry[]
            {
                new AddExtendedQueryTagEntry {
                    Path = weightTag.GetPath(), VR = weightTag.GetDefaultVR().Code, Level = QueryTagLevel.Study
                },
                new AddExtendedQueryTagEntry {
                    Path = sizeTag.GetPath(), VR = sizeTag.GetDefaultVR().Code, Level = QueryTagLevel.Study
                },
            });

            Assert.Equal(OperationRuntimeStatus.Completed, operation.Status);

            // Check specific tag
            DicomWebResponse <GetExtendedQueryTagEntry> getResponse;
            GetExtendedQueryTagEntry entry;

            getResponse = await _client.GetExtendedQueryTagAsync(weightTag.GetPath());

            entry = await getResponse.GetValueAsync();

            Assert.Null(entry.Errors);
            Assert.Equal(QueryStatus.Enabled, entry.QueryStatus);

            getResponse = await _client.GetExtendedQueryTagAsync(sizeTag.GetPath());

            entry = await getResponse.GetValueAsync();

            Assert.Null(entry.Errors);
            Assert.Equal(QueryStatus.Enabled, entry.QueryStatus);

            // Query multiple tags
            // Note: We don't necessarily need to check the tags are the above ones, as another test may have added ones beforehand
            var multipleTags = await _tagManager.GetTagsAsync(2, 0);

            Assert.Equal(2, multipleTags.Count);

            Assert.Equal(multipleTags[0].Path, (await _tagManager.GetTagsAsync(1, 0)).Single().Path);
            Assert.Equal(multipleTags[1].Path, (await _tagManager.GetTagsAsync(1, 1)).Single().Path);

            // QIDO
            DicomWebAsyncEnumerableResponse <DicomDataset> queryResponse = await _client.QueryInstancesAsync($"{weightTag.GetPath()}=50.0");

            DicomDataset[] instances = await queryResponse.ToArrayAsync();

            Assert.Contains(instances, instance => instance.ToInstanceIdentifier().Equals(instance2.ToInstanceIdentifier()));
        }
Example #16
0
 public static AddExtendedQueryTagEntry BuildAddExtendedQueryTagEntry(this DicomTag tag, string vr = null, string privateCreator = null, QueryTagLevel level = QueryTagLevel.Series)
 {
     return(new AddExtendedQueryTagEntry {
         Path = tag.GetPath(), VR = vr ?? tag.GetDefaultVR()?.Code, PrivateCreator = privateCreator, Level = level.ToString()
     });
 }
Example #17
0
 public static GetExtendedQueryTagEntry BuildGetExtendedQueryTagEntry(this DicomTag tag, string vr = null, string privateCreator = null, QueryTagLevel level = QueryTagLevel.Series, ExtendedQueryTagStatus status = ExtendedQueryTagStatus.Ready)
 {
     return(new GetExtendedQueryTagEntry {
         Path = tag.GetPath(), VR = vr ?? tag.GetDefaultVR()?.Code, PrivateCreator = privateCreator, Level = level, Status = status
     });
 }
Example #18
0
        public void GivenStandardTagAsKeyword_WhenNormalizing_ThenVRShouldBeFilled()
        {
            DicomTag tag = DicomTag.DeviceSerialNumber;
            AddExtendedQueryTagEntry entry      = CreateExtendedQueryTagEntry(path: tag.DictionaryEntry.Keyword, tag.GetDefaultVR().Code, null, QueryTagLevel.Instance);
            string expectedPath                 = tag.GetPath();
            AddExtendedQueryTagEntry normalized = entry.Normalize();

            Assert.Equal(normalized.Path, expectedPath);
        }
Example #19
0
        public void GivenVROfLowerCase_WhenNormalizing_ThenVRShouldBeUpperCase()
        {
            DicomTag tag = DicomTag.DeviceLabel;
            AddExtendedQueryTagEntry entry      = CreateExtendedQueryTagEntry(tag.GetPath(), tag.GetDefaultVR().Code.ToLowerInvariant(), null, QueryTagLevel.Instance);
            AddExtendedQueryTagEntry normalized = entry.Normalize();

            Assert.Equal(entry.VR.ToUpperInvariant(), normalized.VR);
        }
Example #20
0
        public async Task GivenValidAndInvalidTagValues_WhenValidate_ThenReturnedValidTagsAndStoredFailure()
        {
            DicomTag     tag1     = DicomTag.DeviceSerialNumber;
            DicomTag     tag2     = DicomTag.DeviceID;
            DicomDataset ds       = Samples.CreateRandomInstanceDataset();
            DicomElement element1 = new DicomLongString(tag1, "testvalue1");
            DicomElement element2 = new DicomLongString(tag2, "testvalue2");

            ds.Add(element1);
            ds.Add(element2);
            QueryTag queryTag1 = new QueryTag(new ExtendedQueryTagStoreEntry(1, tag1.GetPath(), tag1.GetDefaultVR().Code, null, QueryTagLevel.Instance, ExtendedQueryTagStatus.Ready, QueryStatus.Enabled, 0));
            QueryTag queryTag2 = new QueryTag(new ExtendedQueryTagStoreEntry(2, tag2.GetPath(), tag2.GetDefaultVR().Code, null, QueryTagLevel.Instance, ExtendedQueryTagStatus.Ready, QueryStatus.Enabled, 0));

            // Throw exception when validate element1
            var ex = ElementValidationExceptionFactory.CreateDateIsInvalidException("testname", "testvalue");

            _minimumValidator.When(x => x.Validate(element1))
            .Throw(ex);

            // only return querytag2
            long watermark      = 1;
            var  validQueryTags = await _datasetValidator.ValidateAsync(ds, watermark, new[] { queryTag1, queryTag2 });

            Assert.Single(validQueryTags);
            Assert.Same(queryTag2, validQueryTags.First());

            // error for querytag1 is logged
            await _tagErrorsService.Received(1)
            .AddExtendedQueryTagErrorAsync(queryTag1.ExtendedQueryTagStoreEntry.Key, ex.ErrorCode, 1, Arg.Any <CancellationToken>());
        }
        public async Task GivenExtendedQueryTagWithErrors_WhenReindexing_ThenShouldSucceedWithErrors()
        {
            // Define tags
            DicomTag tag      = DicomTag.PatientAge;
            string   tagValue = "053Y";

            // Try to delete this extended query tag if it exists.
            await CleanupExtendedQueryTag(tag);

            // Define DICOM files
            DicomDataset instance1 = Samples.CreateRandomInstanceDataset();
            DicomDataset instance2 = Samples.CreateRandomInstanceDataset();
            DicomDataset instance3 = Samples.CreateRandomInstanceDataset();

            // Annotate files
            // (Disable Auto-validate)
            instance1.NotValidated();
            instance2.NotValidated();

            instance1.Add(tag, "foobar");
            instance2.Add(tag, "invalid");
            instance3.Add(tag, tagValue);

            // Upload files (with a few errors)
            await _instanceManager.StoreAsync(new DicomFile(instance1));

            await _instanceManager.StoreAsync(new DicomFile(instance2));

            await _instanceManager.StoreAsync(new DicomFile(instance3));

            // Add extended query tags
            var operationStatus = await _tagManager.AddTagsAsync(
                new AddExtendedQueryTagEntry[]
            {
                new AddExtendedQueryTagEntry {
                    Path = tag.GetPath(), VR = tag.GetDefaultVR().Code, Level = QueryTagLevel.Instance
                },
            });

            Assert.Equal(OperationRuntimeStatus.Completed, operationStatus.Status);

            // Check specific tag
            GetExtendedQueryTagEntry actual = await _tagManager.GetTagAsync(tag.GetPath());

            Assert.Equal(tag.GetPath(), actual.Path);
            Assert.Equal(2, actual.Errors.Count);
            // It should be disabled by default
            Assert.Equal(QueryStatus.Disabled, actual.QueryStatus);

            // Verify Errors
            var errors = await _tagManager.GetTagErrorsAsync(tag.GetPath(), 2, 0);

            Assert.Equal(2, errors.Count);

            Assert.Equal(errors[0].ErrorMessage, (await _tagManager.GetTagErrorsAsync(tag.GetPath(), 1, 0)).Single().ErrorMessage);
            Assert.Equal(errors[1].ErrorMessage, (await _tagManager.GetTagErrorsAsync(tag.GetPath(), 1, 1)).Single().ErrorMessage);

            var exception = await Assert.ThrowsAsync <DicomWebException>(() => _client.QueryInstancesAsync($"{tag.GetPath()}={tagValue}"));

            Assert.Equal(HttpStatusCode.BadRequest, exception.StatusCode);

            // Enable QIDO on Tag
            actual = await _tagManager.UpdateExtendedQueryTagAsync(tag.GetPath(), new UpdateExtendedQueryTagEntry()
            {
                QueryStatus = QueryStatus.Enabled
            });

            Assert.Equal(QueryStatus.Enabled, actual.QueryStatus);

            var response = await _client.QueryInstancesAsync($"{tag.GetPath()}={tagValue}");

            Assert.True(response.ResponseHeaders.Contains(ErroneousDicomAttributesHeader));
            var values = response.ResponseHeaders.GetValues(ErroneousDicomAttributesHeader);

            Assert.Single(values);
            Assert.Equal(tag.GetPath(), values.First());
            Assert.Equal(HttpStatusCode.OK, response.StatusCode);

            // Verify result
            DicomDataset[] instances = await response.ToArrayAsync();

            Assert.Contains(instances, instance => instance.ToInstanceIdentifier().Equals(instance3.ToInstanceIdentifier()));
        }
Example #22
0
        public void GivenStandardTagAsKeyword_WhenFormalizing_ThenVRShouldBeFilled()
        {
            DicomTag       tag          = DicomTag.DeviceSerialNumber;
            CustomTagEntry entry        = new CustomTagEntry(path: tag.DictionaryEntry.Keyword, tag.GetDefaultVR().Code, CustomTagLevel.Instance, CustomTagStatus.Added);
            string         expectedPath = tag.GetPath();
            CustomTagEntry normalized   = entry.Normalize();

            Assert.Equal(normalized.Path, expectedPath);
        }
Example #23
0
 public static CustomTagEntry BuildCustomTagEntry(this DicomTag tag, CustomTagLevel level = CustomTagLevel.Series, CustomTagStatus status = CustomTagStatus.Added)
 {
     return(new CustomTagEntry(path: tag.GetPath(), vr: tag.GetDefaultVR()?.Code, level: level, status: status));
 }
 public void GivenDicomTag_WhenGetDefaultVR_ThenShouldReturnExpectedValue(DicomTag dicomTag, DicomVR expectedVR)
 {
     Assert.Equal(expectedVR, dicomTag.GetDefaultVR());
 }