Mercurial > hg > orthanc
changeset 3083:683d572424b6 db-changes
IDatabaseWrapper::SetResourcesContent
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Fri, 04 Jan 2019 15:52:19 +0100 |
parents | 847a0ed92654 |
children | 195ba4cbac3f |
files | OrthancServer/IDatabaseWrapper.h OrthancServer/SQLiteDatabaseWrapper.h OrthancServer/Search/Compatibility/CompatibilityDatabaseWrapper.h OrthancServer/Search/Compatibility/ICompatibilityCreateInstance.h OrthancServer/Search/Compatibility/ISetResourcesContent.h OrthancServer/Search/DatabaseLookup.cpp OrthancServer/ServerIndex.cpp OrthancServer/ServerToolbox.cpp OrthancServer/ServerToolbox.h UnitTestsSources/FromDcmtkTests.cpp |
diffstat | 10 files changed, 368 insertions(+), 176 deletions(-) [+] |
line wrap: on
line diff
--- a/OrthancServer/IDatabaseWrapper.h Fri Jan 04 13:52:34 2019 +0100 +++ b/OrthancServer/IDatabaseWrapper.h Fri Jan 04 15:52:19 2019 +0100 @@ -48,6 +48,9 @@ namespace Orthanc { + class ResourcesContent; + + class IDatabaseWrapper : public boost::noncopyable { public: @@ -76,7 +79,6 @@ int64_t seriesId_; }; - virtual ~IDatabaseWrapper() { } @@ -191,14 +193,6 @@ virtual void ClearMainDicomTags(int64_t id) = 0; - virtual void SetMainDicomTag(int64_t id, - const DicomTag& tag, - const std::string& value) = 0; - - virtual void SetIdentifierTag(int64_t id, - const DicomTag& tag, - const std::string& value) = 0; - virtual void SetMetadata(int64_t id, MetadataType type, const std::string& value) = 0; @@ -237,5 +231,7 @@ const std::string& study, const std::string& series, const std::string& instance) = 0; + + virtual void SetResourcesContent(const ResourcesContent& content) = 0; }; }
--- a/OrthancServer/SQLiteDatabaseWrapper.h Fri Jan 04 13:52:34 2019 +0100 +++ b/OrthancServer/SQLiteDatabaseWrapper.h Fri Jan 04 15:52:19 2019 +0100 @@ -37,6 +37,8 @@ #include "../Core/SQLite/Connection.h" #include "Search/Compatibility/ICompatibilityCreateInstance.h" +#include "Search/Compatibility/ISetResourcesContent.h" +#include "ServerToolbox.h" namespace Orthanc { @@ -51,8 +53,8 @@ * exclusion MUST be implemented at a higher level. **/ class SQLiteDatabaseWrapper : - public IDatabaseWrapper, - public Compatibility::ICompatibilityCreateInstance + public Compatibility::ICompatibilityCreateInstance, + public Compatibility::ISetResourcesContent { private: class Transaction;
--- a/OrthancServer/Search/Compatibility/CompatibilityDatabaseWrapper.h Fri Jan 04 13:52:34 2019 +0100 +++ b/OrthancServer/Search/Compatibility/CompatibilityDatabaseWrapper.h Fri Jan 04 15:52:19 2019 +0100 @@ -33,7 +33,9 @@ #pragma once +#include "../../ServerToolbox.h" #include "ICompatibilityCreateInstance.h" +#include "ISetResourcesContent.h" namespace Orthanc { @@ -45,8 +47,8 @@ * during the optimization of the database engine. **/ class CompatibilityDatabaseWrapper : - public IDatabaseWrapper, - public ICompatibilityCreateInstance + public ICompatibilityCreateInstance, + public ISetResourcesContent { public: virtual void ApplyLookupResources(std::list<std::string>& resourcesId,
--- a/OrthancServer/Search/Compatibility/ICompatibilityCreateInstance.h Fri Jan 04 13:52:34 2019 +0100 +++ b/OrthancServer/Search/Compatibility/ICompatibilityCreateInstance.h Fri Jan 04 15:52:19 2019 +0100 @@ -42,6 +42,10 @@ class ICompatibilityCreateInstance : public boost::noncopyable { public: + virtual ~ICompatibilityCreateInstance() + { + } + virtual int64_t CreateResource(const std::string& publicId, ResourceType type) = 0;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/Search/Compatibility/ISetResourcesContent.h Fri Jan 04 15:52:19 2019 +0100 @@ -0,0 +1,69 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2019 Osimis S.A., Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * In addition, as a special exception, the copyright holders of this + * program give permission to link the code of its release with the + * OpenSSL project's "OpenSSL" library (or with modified versions of it + * that use the same license as the "OpenSSL" library), and distribute + * the linked executables. You must obey the GNU General Public License + * in all respects for all of the code used other than "OpenSSL". If you + * modify file(s) with this exception, you may extend this exception to + * your version of the file(s), but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source files + * in the program, then also delete it here. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "../../IDatabaseWrapper.h" +#include "../../ServerToolbox.h" + +namespace Orthanc +{ + namespace Compatibility + { + class ISetResourcesContent : public IDatabaseWrapper + { + public: + virtual ~ISetResourcesContent() + { + } + + virtual void SetResourcesContent(const ResourcesContent& content) + ORTHANC_OVERRIDE + { + content.Store(*this); + } + + virtual void SetMainDicomTag(int64_t id, + const DicomTag& tag, + const std::string& value) = 0; + + virtual void SetIdentifierTag(int64_t id, + const DicomTag& tag, + const std::string& value) = 0; + + virtual void SetMetadata(int64_t id, + MetadataType type, + const std::string& value) = 0; + }; + } +}
--- a/OrthancServer/Search/DatabaseLookup.cpp Fri Jan 04 13:52:34 2019 +0100 +++ b/OrthancServer/Search/DatabaseLookup.cpp Fri Jan 04 15:52:19 2019 +0100 @@ -37,6 +37,8 @@ #include "../ServerToolbox.h" #include "../../Core/DicomParsing/FromDcmtkBridge.h" #include "../../Core/DicomParsing/ToDcmtkBridge.h" +#include "../../Core/OrthancException.h" +#include "../../Core/Toolbox.h" namespace Orthanc {
--- a/OrthancServer/ServerIndex.cpp Fri Jan 04 13:52:34 2019 +0100 +++ b/OrthancServer/ServerIndex.cpp Fri Jan 04 15:52:19 2019 +0100 @@ -777,25 +777,30 @@ // Populate the newly-created resources - // TODO - GROUP THIS - - ServerToolbox::StoreMainDicomTags(db_, instanceId, ResourceType_Instance, dicomSummary); - - if (status.isNewSeries_) + { - ServerToolbox::StoreMainDicomTags(db_, status.seriesId_, ResourceType_Series, dicomSummary); + ResourcesContent content; + + content.AddResource(instanceId, ResourceType_Instance, dicomSummary); + + if (status.isNewSeries_) + { + content.AddResource(status.seriesId_, ResourceType_Series, dicomSummary); + } + + if (status.isNewStudy_) + { + content.AddResource(status.studyId_, ResourceType_Study, dicomSummary); + } + + if (status.isNewPatient_) + { + content.AddResource(status.patientId_, ResourceType_Patient, dicomSummary); + } + + db_.SetResourcesContent(content); } - - if (status.isNewStudy_) - { - ServerToolbox::StoreMainDicomTags(db_, status.studyId_, ResourceType_Study, dicomSummary); - } - - if (status.isNewPatient_) - { - ServerToolbox::StoreMainDicomTags(db_, status.patientId_, ResourceType_Patient, dicomSummary); - } - + // Attach the files to the newly created instance for (Attachments::const_iterator it = attachments.begin(); @@ -2459,10 +2464,14 @@ db_.ClearMainDicomTags(series); db_.ClearMainDicomTags(instance); - ServerToolbox::StoreMainDicomTags(db_, patient, ResourceType_Patient, summary); - ServerToolbox::StoreMainDicomTags(db_, study, ResourceType_Study, summary); - ServerToolbox::StoreMainDicomTags(db_, series, ResourceType_Series, summary); - ServerToolbox::StoreMainDicomTags(db_, instance, ResourceType_Instance, summary); + { + ResourcesContent content; + content.AddResource(patient, ResourceType_Patient, summary); + content.AddResource(study, ResourceType_Study, summary); + content.AddResource(series, ResourceType_Series, summary); + content.AddResource(instance, ResourceType_Instance, summary); + db_.SetResourcesContent(content); + } { std::string s;
--- a/OrthancServer/ServerToolbox.cpp Fri Jan 04 13:52:34 2019 +0100 +++ b/OrthancServer/ServerToolbox.cpp Fri Jan 04 15:52:19 2019 +0100 @@ -35,45 +35,156 @@ #include "ServerToolbox.h" #include "../Core/DicomFormat/DicomArray.h" +#include "../Core/DicomParsing/ParsedDicomFile.h" #include "../Core/FileStorage/StorageAccessor.h" #include "../Core/Logging.h" #include "../Core/OrthancException.h" +#include "IDatabaseWrapper.h" +#include "ServerContext.h" #include <cassert> namespace Orthanc { + static const DicomTag PATIENT_IDENTIFIERS[] = + { + DICOM_TAG_PATIENT_ID, + DICOM_TAG_PATIENT_NAME, + DICOM_TAG_PATIENT_BIRTH_DATE + }; + + static const DicomTag STUDY_IDENTIFIERS[] = + { + DICOM_TAG_PATIENT_ID, + DICOM_TAG_PATIENT_NAME, + DICOM_TAG_PATIENT_BIRTH_DATE, + DICOM_TAG_STUDY_INSTANCE_UID, + DICOM_TAG_ACCESSION_NUMBER, + DICOM_TAG_STUDY_DESCRIPTION, + DICOM_TAG_STUDY_DATE + }; + + static const DicomTag SERIES_IDENTIFIERS[] = + { + DICOM_TAG_SERIES_INSTANCE_UID + }; + + static const DicomTag INSTANCE_IDENTIFIERS[] = + { + DICOM_TAG_SOP_INSTANCE_UID + }; + + + void ResourcesContent::Store(Compatibility::ISetResourcesContent& compatibility) const + { + for (std::list<TagValue>::const_iterator + it = tags_.begin(); it != tags_.end(); ++it) + { + if (it->isIdentifier_) + { + compatibility.SetIdentifierTag(it->resourceId_, it->tag_, it->value_); + } + else + { + compatibility.SetMainDicomTag(it->resourceId_, it->tag_, it->value_); + } + } + + for (std::list<Metadata>::const_iterator + it = metadata_.begin(); it != metadata_.end(); ++it) + { + compatibility.SetMetadata(it->resourceId_, it->metadata_, it->value_); + } + } + + + static void StoreMainDicomTagsInternal(ResourcesContent& target, + int64_t resource, + const DicomMap& tags) + { + DicomArray flattened(tags); + + for (size_t i = 0; i < flattened.GetSize(); i++) + { + const DicomElement& element = flattened.GetElement(i); + const DicomTag& tag = element.GetTag(); + const DicomValue& value = element.GetValue(); + if (!value.IsNull() && + !value.IsBinary()) + { + target.AddMainDicomTag(resource, tag, element.GetValue().GetContent()); + } + } + } + + + static void StoreIdentifiers(ResourcesContent& target, + int64_t resource, + ResourceType level, + const DicomMap& map) + { + const DicomTag* tags; + size_t size; + + ServerToolbox::LoadIdentifiers(tags, size, level); + + for (size_t i = 0; i < size; i++) + { + // The identifiers tags are a subset of the main DICOM tags + assert(DicomMap::IsMainDicomTag(tags[i])); + + const DicomValue* value = map.TestAndGetValue(tags[i]); + if (value != NULL && + !value->IsNull() && + !value->IsBinary()) + { + std::string s = ServerToolbox::NormalizeIdentifier(value->GetContent()); + target.AddIdentifierTag(resource, tags[i], s); + } + } + } + + + void ResourcesContent::AddResource(int64_t resource, + ResourceType level, + const DicomMap& dicomSummary) + { + StoreIdentifiers(*this, resource, level, dicomSummary); + + DicomMap tags; + + switch (level) + { + case ResourceType_Patient: + dicomSummary.ExtractPatientInformation(tags); + break; + + case ResourceType_Study: + // Duplicate the patient tags at the study level (new in Orthanc 0.9.5 - db v6) + dicomSummary.ExtractPatientInformation(tags); + StoreMainDicomTagsInternal(*this, resource, tags); + + dicomSummary.ExtractStudyInformation(tags); + break; + + case ResourceType_Series: + dicomSummary.ExtractSeriesInformation(tags); + break; + + case ResourceType_Instance: + dicomSummary.ExtractInstanceInformation(tags); + break; + + default: + throw OrthancException(ErrorCode_InternalError); + } + + StoreMainDicomTagsInternal(*this, resource, tags); + } + + namespace ServerToolbox { - static const DicomTag patientIdentifiers[] = - { - DICOM_TAG_PATIENT_ID, - DICOM_TAG_PATIENT_NAME, - DICOM_TAG_PATIENT_BIRTH_DATE - }; - - static const DicomTag studyIdentifiers[] = - { - DICOM_TAG_PATIENT_ID, - DICOM_TAG_PATIENT_NAME, - DICOM_TAG_PATIENT_BIRTH_DATE, - DICOM_TAG_STUDY_INSTANCE_UID, - DICOM_TAG_ACCESSION_NUMBER, - DICOM_TAG_STUDY_DESCRIPTION, - DICOM_TAG_STUDY_DATE - }; - - static const DicomTag seriesIdentifiers[] = - { - DICOM_TAG_SERIES_INSTANCE_UID - }; - - static const DicomTag instanceIdentifiers[] = - { - DICOM_TAG_SOP_INSTANCE_UID - }; - - void SimplifyTags(Json::Value& target, const Json::Value& source, DicomToJsonFormat format) @@ -138,94 +249,6 @@ } - static void StoreMainDicomTagsInternal(IDatabaseWrapper& database, - int64_t resource, - const DicomMap& tags) - { - DicomArray flattened(tags); - - for (size_t i = 0; i < flattened.GetSize(); i++) - { - const DicomElement& element = flattened.GetElement(i); - const DicomTag& tag = element.GetTag(); - const DicomValue& value = element.GetValue(); - if (!value.IsNull() && - !value.IsBinary()) - { - database.SetMainDicomTag(resource, tag, element.GetValue().GetContent()); - } - } - } - - - static void StoreIdentifiers(IDatabaseWrapper& database, - int64_t resource, - ResourceType level, - const DicomMap& map) - { - const DicomTag* tags; - size_t size; - - LoadIdentifiers(tags, size, level); - - for (size_t i = 0; i < size; i++) - { - // The identifiers tags are a subset of the main DICOM tags - assert(DicomMap::IsMainDicomTag(tags[i])); - - const DicomValue* value = map.TestAndGetValue(tags[i]); - if (value != NULL && - !value->IsNull() && - !value->IsBinary()) - { - std::string s = NormalizeIdentifier(value->GetContent()); - database.SetIdentifierTag(resource, tags[i], s); - } - } - } - - - void StoreMainDicomTags(IDatabaseWrapper& database, - int64_t resource, - ResourceType level, - const DicomMap& dicomSummary) - { - // WARNING: The database should be locked with a transaction! - - StoreIdentifiers(database, resource, level, dicomSummary); - - DicomMap tags; - - switch (level) - { - case ResourceType_Patient: - dicomSummary.ExtractPatientInformation(tags); - break; - - case ResourceType_Study: - // Duplicate the patient tags at the study level (new in Orthanc 0.9.5 - db v6) - dicomSummary.ExtractPatientInformation(tags); - StoreMainDicomTagsInternal(database, resource, tags); - - dicomSummary.ExtractStudyInformation(tags); - break; - - case ResourceType_Series: - dicomSummary.ExtractSeriesInformation(tags); - break; - - case ResourceType_Instance: - dicomSummary.ExtractInstanceInformation(tags); - break; - - default: - throw OrthancException(ErrorCode_InternalError); - } - - StoreMainDicomTagsInternal(database, resource, tags); - } - - bool FindOneChildInstance(int64_t& result, IDatabaseWrapper& database, int64_t resource, @@ -335,7 +358,10 @@ dicom.ExtractDicomSummary(dicomSummary); database.ClearMainDicomTags(resource); - StoreMainDicomTags(database, resource, level, dicomSummary); + + ResourcesContent tags; + tags.AddResource(resource, level, dicomSummary); + database.SetResourcesContent(tags); } catch (OrthancException&) { @@ -354,23 +380,23 @@ switch (level) { case ResourceType_Patient: - tags = patientIdentifiers; - size = sizeof(patientIdentifiers) / sizeof(DicomTag); + tags = PATIENT_IDENTIFIERS; + size = sizeof(PATIENT_IDENTIFIERS) / sizeof(DicomTag); break; case ResourceType_Study: - tags = studyIdentifiers; - size = sizeof(studyIdentifiers) / sizeof(DicomTag); + tags = STUDY_IDENTIFIERS; + size = sizeof(STUDY_IDENTIFIERS) / sizeof(DicomTag); break; case ResourceType_Series: - tags = seriesIdentifiers; - size = sizeof(seriesIdentifiers) / sizeof(DicomTag); + tags = SERIES_IDENTIFIERS; + size = sizeof(SERIES_IDENTIFIERS) / sizeof(DicomTag); break; case ResourceType_Instance: - tags = instanceIdentifiers; - size = sizeof(instanceIdentifiers) / sizeof(DicomTag); + tags = INSTANCE_IDENTIFIERS; + size = sizeof(INSTANCE_IDENTIFIERS) / sizeof(DicomTag); break; default:
--- a/OrthancServer/ServerToolbox.h Fri Jan 04 13:52:34 2019 +0100 +++ b/OrthancServer/ServerToolbox.h Fri Jan 04 15:52:19 2019 +0100 @@ -33,23 +33,104 @@ #pragma once -#include "ServerContext.h" +#include "ServerEnumerations.h" #include <json/json.h> +#include <boost/noncopyable.hpp> +#include <list> namespace Orthanc { + class ServerContext; + class IDatabaseWrapper; + class DicomMap; + class IStorageArea; + + namespace Compatibility + { + class ISetResourcesContent; + } + + + // TODO - Move this to a separate file + class ResourcesContent : public boost::noncopyable + { + private: + struct TagValue + { + int64_t resourceId_; + bool isIdentifier_; + DicomTag tag_; + std::string value_; + + TagValue(int64_t resourceId, + bool isIdentifier, + const DicomTag& tag, + const std::string& value) : + resourceId_(resourceId), + isIdentifier_(isIdentifier), + tag_(tag), + value_(value) + { + } + }; + + struct Metadata + { + int64_t resourceId_; + MetadataType metadata_; + std::string value_; + + Metadata(int64_t resourceId, + MetadataType metadata, + const std::string& value) : + resourceId_(resourceId), + metadata_(metadata), + value_(value) + { + } + }; + + std::list<TagValue> tags_; + std::list<Metadata> metadata_; + + public: + void AddMainDicomTag(int64_t resourceId, + const DicomTag& tag, + const std::string& value) + { + tags_.push_back(TagValue(resourceId, false, tag, value)); + } + + void AddIdentifierTag(int64_t resourceId, + const DicomTag& tag, + const std::string& value) + { + tags_.push_back(TagValue(resourceId, true, tag, value)); + } + + void AddMetadata(int64_t resourceId, + MetadataType metadata, + const std::string& value) + { + metadata_.push_back(Metadata(resourceId, metadata, value)); + } + + void AddResource(int64_t resource, + ResourceType level, + const DicomMap& dicomSummary); + + // WARNING: The database should be locked with a transaction! + void Store(Compatibility::ISetResourcesContent& target) const; + }; + + namespace ServerToolbox { void SimplifyTags(Json::Value& target, const Json::Value& source, DicomToJsonFormat format); - void StoreMainDicomTags(IDatabaseWrapper& database, - int64_t resource, - ResourceType level, - const DicomMap& dicomSummary); - bool FindOneChildInstance(int64_t& result, IDatabaseWrapper& database, int64_t resource,
--- a/UnitTestsSources/FromDcmtkTests.cpp Fri Jan 04 13:52:34 2019 +0100 +++ b/UnitTestsSources/FromDcmtkTests.cpp Fri Jan 04 15:52:19 2019 +0100 @@ -34,21 +34,22 @@ #include "PrecompiledHeadersUnitTests.h" #include "gtest/gtest.h" -#include "../Core/DicomParsing/FromDcmtkBridge.h" -#include "../Core/DicomParsing/ToDcmtkBridge.h" +#include "../Core/DicomNetworking/DicomFindAnswers.h" #include "../Core/DicomParsing/DicomModification.h" -#include "../OrthancServer/ServerToolbox.h" -#include "../Core/OrthancException.h" +#include "../Core/DicomParsing/FromDcmtkBridge.h" +#include "../Core/DicomParsing/Internals/DicomImageDecoder.h" +#include "../Core/DicomParsing/ToDcmtkBridge.h" +#include "../Core/Endianness.h" +#include "../Core/Images/Image.h" #include "../Core/Images/ImageBuffer.h" +#include "../Core/Images/ImageProcessing.h" #include "../Core/Images/PngReader.h" #include "../Core/Images/PngWriter.h" -#include "../Core/Images/Image.h" -#include "../Core/Images/ImageProcessing.h" -#include "../Core/Endianness.h" +#include "../Core/OrthancException.h" +#include "../Core/SystemToolbox.h" +#include "../OrthancServer/ServerToolbox.h" +#include "../Plugins/Engine/PluginsEnumerations.h" #include "../Resources/EncodingTests.h" -#include "../Core/DicomNetworking/DicomFindAnswers.h" -#include "../Core/DicomParsing/Internals/DicomImageDecoder.h" -#include "../Plugins/Engine/PluginsEnumerations.h" #include <dcmtk/dcmdata/dcelem.h> #include <dcmtk/dcmdata/dcdeftag.h>