Mercurial > hg > orthanc
changeset 3187:4bbadcd03966
refactoring retrieval of metadata from database
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Mon, 04 Feb 2019 12:06:19 +0100 |
parents | 5d1f5984dc41 |
children | 70356580e310 |
files | CMakeLists.txt OrthancServer/Database/Compatibility/ILookupResourceAndParent.cpp OrthancServer/Database/Compatibility/ILookupResourceAndParent.h OrthancServer/Database/IDatabaseWrapper.h OrthancServer/Database/SQLiteDatabaseWrapper.cpp OrthancServer/Database/SQLiteDatabaseWrapper.h OrthancServer/LuaScripting.cpp OrthancServer/OrthancRestApi/OrthancRestResources.cpp OrthancServer/ServerIndex.cpp OrthancServer/ServerIndex.h Plugins/Engine/OrthancPluginDatabase.cpp Plugins/Engine/OrthancPluginDatabase.h UnitTestsSources/DicomMapTests.cpp UnitTestsSources/ServerIndexTests.cpp |
diffstat | 14 files changed, 491 insertions(+), 178 deletions(-) [+] |
line wrap: on
line diff
--- a/CMakeLists.txt Fri Feb 01 09:28:12 2019 +0100 +++ b/CMakeLists.txt Mon Feb 04 12:06:19 2019 +0100 @@ -56,6 +56,7 @@ OrthancServer/Database/Compatibility/DatabaseLookup.cpp OrthancServer/Database/Compatibility/ICreateInstance.cpp OrthancServer/Database/Compatibility/IGetChildrenMetadata.cpp + OrthancServer/Database/Compatibility/ILookupResourceAndParent.cpp OrthancServer/Database/Compatibility/ILookupResources.cpp OrthancServer/Database/Compatibility/SetOfResources.cpp OrthancServer/Database/ResourcesContent.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/Database/Compatibility/ILookupResourceAndParent.cpp Mon Feb 04 12:06:19 2019 +0100 @@ -0,0 +1,71 @@ +/** + * 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/>. + **/ + + +#include "../../PrecompiledHeadersServer.h" +#include "ILookupResourceAndParent.h" + +#include "../../../Core/OrthancException.h" + +namespace Orthanc +{ + namespace Compatibility + { + bool ILookupResourceAndParent::Apply(ILookupResourceAndParent& database, + int64_t& id, + ResourceType& type, + std::string& parentPublicId, + const std::string& publicId) + { + if (!database.LookupResource(id, type, publicId)) + { + return false; + } + else if (type == ResourceType_Patient) + { + parentPublicId.clear(); + return true; + } + else + { + int64_t parentId; + if (!database.LookupParent(parentId, id)) + { + throw OrthancException(ErrorCode_InternalError); + } + + parentPublicId = database.GetPublicId(parentId); + return true; + } + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/Database/Compatibility/ILookupResourceAndParent.h Mon Feb 04 12:06:19 2019 +0100 @@ -0,0 +1,64 @@ +/** + * 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 "../../ServerEnumerations.h" + +#include <boost/noncopyable.hpp> +#include <list> + +namespace Orthanc +{ + namespace Compatibility + { + class ILookupResourceAndParent : public boost::noncopyable + { + public: + virtual bool LookupResource(int64_t& id, + ResourceType& type, + const std::string& publicId) = 0; + + virtual bool LookupParent(int64_t& parentId, + int64_t resourceId) = 0; + + virtual std::string GetPublicId(int64_t resourceId) = 0; + + static bool Apply(ILookupResourceAndParent& database, + int64_t& id, + ResourceType& type, + std::string& parentPublicId, + const std::string& publicId); + }; + } +}
--- a/OrthancServer/Database/IDatabaseWrapper.h Fri Feb 01 09:28:12 2019 +0100 +++ b/OrthancServer/Database/IDatabaseWrapper.h Mon Feb 04 12:06:19 2019 +0100 @@ -153,9 +153,6 @@ virtual bool IsProtectedPatient(int64_t internalId) = 0; - virtual void ListAvailableMetadata(std::list<MetadataType>& target, - int64_t id) = 0; - virtual void ListAvailableAttachments(std::list<FileContentType>& target, int64_t id) = 0; @@ -245,5 +242,15 @@ MetadataType metadata) = 0; virtual int64_t GetLastChangeIndex() = 0; + + + /** + * Primitives introduced in Orthanc 1.5.4 + **/ + + virtual bool LookupResourceAndParent(int64_t& id, + ResourceType& type, + std::string& parentPublicId, + const std::string& publicId) = 0; }; }
--- a/OrthancServer/Database/SQLiteDatabaseWrapper.cpp Fri Feb 01 09:28:12 2019 +0100 +++ b/OrthancServer/Database/SQLiteDatabaseWrapper.cpp Mon Feb 04 12:06:19 2019 +0100 @@ -761,21 +761,6 @@ } - void SQLiteDatabaseWrapper::ListAvailableMetadata(std::list<MetadataType>& target, - int64_t id) - { - target.clear(); - - SQLite::Statement s(db_, SQLITE_FROM_HERE, "SELECT type FROM Metadata WHERE id=?"); - s.BindInt64(0, id); - - while (s.Step()) - { - target.push_back(static_cast<MetadataType>(s.ColumnInt(0))); - } - } - - void SQLiteDatabaseWrapper::AddAttachment(int64_t id, const FileInfo& attachment) {
--- a/OrthancServer/Database/SQLiteDatabaseWrapper.h Fri Feb 01 09:28:12 2019 +0100 +++ b/OrthancServer/Database/SQLiteDatabaseWrapper.h Mon Feb 04 12:06:19 2019 +0100 @@ -38,6 +38,7 @@ #include "../../Core/SQLite/Connection.h" #include "Compatibility/ICreateInstance.h" #include "Compatibility/IGetChildrenMetadata.h" +#include "Compatibility/ILookupResourceAndParent.h" #include "Compatibility/ISetResourcesContent.h" namespace Orthanc @@ -56,6 +57,7 @@ public IDatabaseWrapper, public Compatibility::ICreateInstance, public Compatibility::IGetChildrenMetadata, + public Compatibility::ILookupResourceAndParent, public Compatibility::ISetResourcesContent { private: @@ -224,10 +226,6 @@ MetadataType type) ORTHANC_OVERRIDE; - virtual void ListAvailableMetadata(std::list<MetadataType>& target, - int64_t id) - ORTHANC_OVERRIDE; - virtual void AddAttachment(int64_t id, const FileInfo& attachment) ORTHANC_OVERRIDE; @@ -361,5 +359,14 @@ virtual int64_t GetLastChangeIndex() ORTHANC_OVERRIDE; virtual void TagMostRecentPatient(int64_t patient) ORTHANC_OVERRIDE; + + virtual bool LookupResourceAndParent(int64_t& id, + ResourceType& type, + std::string& parentPublicId, + const std::string& publicId) + ORTHANC_OVERRIDE + { + return ILookupResourceAndParent::Apply(*this, id, type, parentPublicId, publicId); + } }; }
--- a/OrthancServer/LuaScripting.cpp Fri Feb 01 09:28:12 2019 +0100 +++ b/OrthancServer/LuaScripting.cpp Mon Feb 04 12:06:19 2019 +0100 @@ -164,23 +164,37 @@ } } - Json::Value tags, metadata; - if (that.context_.GetIndex().LookupResource(tags, change_.GetPublicId(), change_.GetResourceType()) && - that.context_.GetIndex().GetMetadata(metadata, change_.GetPublicId())) + Json::Value tags; + + if (that.context_.GetIndex().LookupResource(tags, change_.GetPublicId(), change_.GetResourceType())) { - LuaScripting::Lock lock(that); + std::map<MetadataType, std::string> metadata; + that.context_.GetIndex().GetAllMetadata(metadata, change_.GetPublicId()); + + Json::Value formattedMetadata = Json::objectValue; - if (lock.GetLua().IsExistingFunction(name)) + for (std::map<MetadataType, std::string>::const_iterator + it = metadata.begin(); it != metadata.end(); ++it) { - that.InitializeJob(); + std::string key = EnumerationToString(it->first); + formattedMetadata[key] = it->second; + } + + { + LuaScripting::Lock lock(that); - LuaFunctionCall call(lock.GetLua(), name); - call.PushString(change_.GetPublicId()); - call.PushJson(tags["MainDicomTags"]); - call.PushJson(metadata); - call.Execute(); + if (lock.GetLua().IsExistingFunction(name)) + { + that.InitializeJob(); - that.SubmitJob(); + LuaFunctionCall call(lock.GetLua(), name); + call.PushString(change_.GetPublicId()); + call.PushJson(tags["MainDicomTags"]); + call.PushJson(formattedMetadata); + call.Execute(); + + that.SubmitJob(); + } } } }
--- a/OrthancServer/OrthancRestApi/OrthancRestResources.cpp Fri Feb 01 09:28:12 2019 +0100 +++ b/OrthancServer/OrthancRestApi/OrthancRestResources.cpp Mon Feb 04 12:06:19 2019 +0100 @@ -705,9 +705,9 @@ CheckValidResourceType(call); std::string publicId = call.GetUriComponent("id", ""); - std::list<MetadataType> metadata; + std::map<MetadataType, std::string> metadata; - OrthancRestApi::GetIndex(call).ListAvailableMetadata(metadata, publicId); + OrthancRestApi::GetIndex(call).GetAllMetadata(metadata, publicId); Json::Value result; @@ -715,25 +715,21 @@ { result = Json::objectValue; - for (std::list<MetadataType>::const_iterator + for (std::map<MetadataType, std::string>::const_iterator it = metadata.begin(); it != metadata.end(); ++it) { - std::string value; - if (OrthancRestApi::GetIndex(call).LookupMetadata(value, publicId, *it)) - { - std::string key = EnumerationToString(*it); - result[key] = value; - } + std::string key = EnumerationToString(it->first); + result[key] = it->second; } } else { result = Json::arrayValue; - for (std::list<MetadataType>::const_iterator + for (std::map<MetadataType, std::string>::const_iterator it = metadata.begin(); it != metadata.end(); ++it) { - result.append(EnumerationToString(*it)); + result.append(EnumerationToString(it->first)); } }
--- a/OrthancServer/ServerIndex.cpp Fri Feb 01 09:28:12 2019 +0100 +++ b/OrthancServer/ServerIndex.cpp Mon Feb 04 12:06:19 2019 +0100 @@ -559,12 +559,30 @@ - bool ServerIndex::GetMetadataAsInteger(int64_t& result, - int64_t id, - MetadataType type) + static bool LookupStringMetadata(std::string& result, + const std::map<MetadataType, std::string>& metadata, + MetadataType type) + { + std::map<MetadataType, std::string>::const_iterator found = metadata.find(type); + + if (found == metadata.end()) + { + return false; + } + else + { + result = found->second; + return true; + } + } + + + static bool LookupIntegerMetadata(int64_t& result, + const std::map<MetadataType, std::string>& metadata, + MetadataType type) { std::string s; - if (!db_.LookupMetadata(s, id, type)) + if (!LookupStringMetadata(s, metadata, type)) { return false; } @@ -947,10 +965,14 @@ // Check whether the series of this new instance is now completed - SeriesStatus seriesStatus = GetSeriesStatus(status.seriesId_); - if (seriesStatus == SeriesStatus_Complete) + int64_t expectedNumberOfInstances; + if (ComputeExpectedNumberOfInstances(expectedNumberOfInstances, dicomSummary)) { - LogChange(status.seriesId_, ChangeType_CompletedSeries, ResourceType_Series, hashSeries); + SeriesStatus seriesStatus = GetSeriesStatus(status.seriesId_, expectedNumberOfInstances); + if (seriesStatus == SeriesStatus_Complete) + { + LogChange(status.seriesId_, ChangeType_CompletedSeries, ResourceType_Series, hashSeries); + } } @@ -1037,21 +1059,6 @@ } - SeriesStatus ServerIndex::GetSeriesStatus(int64_t id) - { - // Get the expected number of instances in this series (from the metadata) - int64_t expected; - if (!GetMetadataAsInteger(expected, id, MetadataType_Series_ExpectedNumberOfInstances)) - { - return SeriesStatus_Unknown; - } - else - { - return GetSeriesStatus(id, expected); - } - } - - void ServerIndex::MainDicomTagsToJson(Json::Value& target, int64_t resourceId, ResourceType resourceType) @@ -1090,22 +1097,27 @@ // Lookup for the requested resource int64_t id; ResourceType type; - if (!db_.LookupResource(id, type, publicId) || + std::string parent; + if (!db_.LookupResourceAndParent(id, type, parent, publicId) || type != expectedType) { return false; } - // Find the parent resource (if it exists) - if (type != ResourceType_Patient) + // Set information about the parent resource (if it exists) + if (type == ResourceType_Patient) { - int64_t parentId; - if (!db_.LookupParent(parentId, id)) + if (!parent.empty()) { - throw OrthancException(ErrorCode_InternalError); + throw OrthancException(ErrorCode_DatabasePlugin); } - - std::string parent = db_.GetPublicId(parentId); + } + else + { + if (parent.empty()) + { + throw OrthancException(ErrorCode_DatabasePlugin); + } switch (type) { @@ -1159,6 +1171,10 @@ } } + // Extract the metadata + std::map<MetadataType, std::string> metadata; + db_.GetAllMetadata(metadata, id); + // Set the resource type switch (type) { @@ -1173,16 +1189,17 @@ case ResourceType_Series: { result["Type"] = "Series"; - result["Status"] = EnumerationToString(GetSeriesStatus(id)); int64_t i; - if (GetMetadataAsInteger(i, id, MetadataType_Series_ExpectedNumberOfInstances)) + if (LookupIntegerMetadata(i, metadata, MetadataType_Series_ExpectedNumberOfInstances)) { result["ExpectedNumberOfInstances"] = static_cast<int>(i); + result["Status"] = EnumerationToString(GetSeriesStatus(id, i)); } else { result["ExpectedNumberOfInstances"] = Json::nullValue; + result["Status"] = EnumerationToString(SeriesStatus_Unknown); } break; @@ -1202,7 +1219,7 @@ result["FileUuid"] = attachment.GetUuid(); int64_t i; - if (GetMetadataAsInteger(i, id, MetadataType_Instance_IndexInSeries)) + if (LookupIntegerMetadata(i, metadata, MetadataType_Instance_IndexInSeries)) { result["IndexInSeries"] = static_cast<int>(i); } @@ -1224,12 +1241,12 @@ std::string tmp; - if (db_.LookupMetadata(tmp, id, MetadataType_AnonymizedFrom)) + if (LookupStringMetadata(tmp, metadata, MetadataType_AnonymizedFrom)) { result["AnonymizedFrom"] = tmp; } - if (db_.LookupMetadata(tmp, id, MetadataType_ModifiedFrom)) + if (LookupStringMetadata(tmp, metadata, MetadataType_ModifiedFrom)) { result["ModifiedFrom"] = tmp; } @@ -1240,7 +1257,7 @@ { result["IsStable"] = !unstableResources_.Contains(id); - if (db_.LookupMetadata(tmp, id, MetadataType_LastUpdate)) + if (LookupStringMetadata(tmp, metadata, MetadataType_LastUpdate)) { result["LastUpdate"] = tmp; } @@ -1825,19 +1842,19 @@ } - void ServerIndex::ListAvailableMetadata(std::list<MetadataType>& target, - const std::string& publicId) + void ServerIndex::GetAllMetadata(std::map<MetadataType, std::string>& target, + const std::string& publicId) { boost::mutex::scoped_lock lock(mutex_); - ResourceType rtype; + ResourceType type; int64_t id; - if (!db_.LookupResource(id, rtype, publicId)) + if (!db_.LookupResource(id, type, publicId)) { throw OrthancException(ErrorCode_UnknownResource); } - db_.ListAvailableMetadata(target, id); + return db_.GetAllMetadata(target, id); } @@ -2214,41 +2231,6 @@ } - bool ServerIndex::GetMetadata(Json::Value& target, - const std::string& publicId) - { - boost::mutex::scoped_lock lock(mutex_); - - target = Json::objectValue; - - ResourceType type; - int64_t id; - if (!db_.LookupResource(id, type, publicId)) - { - return false; - } - - std::list<MetadataType> metadata; - db_.ListAvailableMetadata(metadata, id); - - for (std::list<MetadataType>::const_iterator - it = metadata.begin(); it != metadata.end(); ++it) - { - std::string key = EnumerationToString(*it); - - std::string value; - if (!db_.LookupMetadata(value, id, *it)) - { - value.clear(); - } - - target[key] = value; - } - - return true; - } - - void ServerIndex::SetGlobalProperty(GlobalProperty property, const std::string& value) {
--- a/OrthancServer/ServerIndex.h Fri Feb 01 09:28:12 2019 +0100 +++ b/OrthancServer/ServerIndex.h Mon Feb 04 12:06:19 2019 +0100 @@ -84,8 +84,6 @@ int64_t resourceId, ResourceType resourceType); - SeriesStatus GetSeriesStatus(int64_t id); - bool IsRecyclingNeeded(uint64_t instanceSize); void Recycle(uint64_t instanceSize, @@ -97,10 +95,6 @@ Orthanc::ResourceType type, const std::string& publicId); - bool GetMetadataAsInteger(int64_t& result, - int64_t id, - MetadataType type); - void LogChange(int64_t internalId, ChangeType changeType, ResourceType resourceType, @@ -211,16 +205,13 @@ void DeleteMetadata(const std::string& publicId, MetadataType type); + void GetAllMetadata(std::map<MetadataType, std::string>& target, + const std::string& publicId); + bool LookupMetadata(std::string& target, const std::string& publicId, MetadataType type); - void ListAvailableMetadata(std::list<MetadataType>& target, - const std::string& publicId); - - bool GetMetadata(Json::Value& target, - const std::string& publicId); - void ListAvailableAttachments(std::list<FileContentType>& target, const std::string& publicId, ResourceType expectedType);
--- a/Plugins/Engine/OrthancPluginDatabase.cpp Fri Feb 01 09:28:12 2019 +0100 +++ b/Plugins/Engine/OrthancPluginDatabase.cpp Mon Feb 04 12:06:19 2019 +0100 @@ -390,21 +390,34 @@ void OrthancPluginDatabase::GetAllMetadata(std::map<MetadataType, std::string>& target, int64_t id) { - std::list<MetadataType> metadata; - ListAvailableMetadata(metadata, id); + // TODO - Add primitive in SDK target.clear(); - for (std::list<MetadataType>::const_iterator - it = metadata.begin(); it != metadata.end(); ++it) + ResetAnswers(); + CheckSuccess(backend_.listAvailableMetadata(GetContext(), payload_, id)); + + if (type_ != _OrthancPluginDatabaseAnswerType_None && + type_ != _OrthancPluginDatabaseAnswerType_Int32) { - std::string value; - if (!LookupMetadata(value, id, *it)) + throw OrthancException(ErrorCode_DatabasePlugin); + } + + target.clear(); + + if (type_ == _OrthancPluginDatabaseAnswerType_Int32) + { + for (std::list<int32_t>::const_iterator + it = answerInt32_.begin(); it != answerInt32_.end(); ++it) { - throw OrthancException(ErrorCode_DatabasePlugin); + MetadataType type = static_cast<MetadataType>(*it); + + std::string value; + if (LookupMetadata(value, id, type)) + { + target[type] = value; + } } - - target[*it] = value; } } @@ -624,31 +637,6 @@ } - void OrthancPluginDatabase::ListAvailableMetadata(std::list<MetadataType>& target, - int64_t id) - { - ResetAnswers(); - CheckSuccess(backend_.listAvailableMetadata(GetContext(), payload_, id)); - - if (type_ != _OrthancPluginDatabaseAnswerType_None && - type_ != _OrthancPluginDatabaseAnswerType_Int32) - { - throw OrthancException(ErrorCode_DatabasePlugin); - } - - target.clear(); - - if (type_ == _OrthancPluginDatabaseAnswerType_Int32) - { - for (std::list<int32_t>::const_iterator - it = answerInt32_.begin(); it != answerInt32_.end(); ++it) - { - target.push_back(static_cast<MetadataType>(*it)); - } - } - } - - void OrthancPluginDatabase::ListAvailableAttachments(std::list<FileContentType>& target, int64_t id) { @@ -1431,4 +1419,14 @@ CheckSuccess(extensions_.tagMostRecentPatient(payload_, patient)); } } + + + bool OrthancPluginDatabase::LookupResourceAndParent(int64_t& id, + ResourceType& type, + std::string& parentPublicId, + const std::string& publicId) + { + // TODO - Add primitive in SDK + return ILookupResourceAndParent::Apply(*this, id, type, parentPublicId, publicId); + } }
--- a/Plugins/Engine/OrthancPluginDatabase.h Fri Feb 01 09:28:12 2019 +0100 +++ b/Plugins/Engine/OrthancPluginDatabase.h Mon Feb 04 12:06:19 2019 +0100 @@ -39,6 +39,7 @@ #include "../../OrthancServer/Database/Compatibility/ICreateInstance.h" #include "../../OrthancServer/Database/Compatibility/IGetChildrenMetadata.h" #include "../../OrthancServer/Database/Compatibility/ILookupResources.h" +#include "../../OrthancServer/Database/Compatibility/ILookupResourceAndParent.h" #include "../../OrthancServer/Database/Compatibility/ISetResourcesContent.h" #include "../Include/orthanc/OrthancCDatabasePlugin.h" #include "PluginsErrorDictionary.h" @@ -50,6 +51,7 @@ public Compatibility::ICreateInstance, public Compatibility::IGetChildrenMetadata, public Compatibility::ILookupResources, + public Compatibility::ILookupResourceAndParent, public Compatibility::ISetResourcesContent { private: @@ -225,10 +227,6 @@ virtual bool IsProtectedPatient(int64_t internalId) ORTHANC_OVERRIDE; - virtual void ListAvailableMetadata(std::list<MetadataType>& target, - int64_t id) - ORTHANC_OVERRIDE; - virtual void ListAvailableAttachments(std::list<FileContentType>& target, int64_t id) ORTHANC_OVERRIDE; @@ -364,6 +362,12 @@ virtual int64_t GetLastChangeIndex() ORTHANC_OVERRIDE; virtual void TagMostRecentPatient(int64_t patient) ORTHANC_OVERRIDE; + + virtual bool LookupResourceAndParent(int64_t& id, + ResourceType& type, + std::string& parentPublicId, + const std::string& publicId) + ORTHANC_OVERRIDE; }; }
--- a/UnitTestsSources/DicomMapTests.cpp Fri Feb 01 09:28:12 2019 +0100 +++ b/UnitTestsSources/DicomMapTests.cpp Mon Feb 04 12:06:19 2019 +0100 @@ -551,3 +551,196 @@ ASSERT_EQ("F", b.GetValue(DICOM_TAG_SLICE_THICKNESS).GetContent()); ASSERT_FALSE(b.HasOnlyMainDicomTags()); } + + + + +#if 0 + +namespace Orthanc +{ + class DicomJsonVisitor : public ITagVisitor + { + private: + Json::Value result_; + std::string bulkUriRoot_; + + static std::string FormatTag(const DicomTag& tag) + { + char buf[16]; + sprintf(buf, "%04X%04X", tag.GetGroup(), tag.GetElement()); + return std::string(buf); + } + + Json::Value& CreateNode(const std::vector<DicomTag>& parentTags, + const std::vector<size_t>& parentIndexes, + const DicomTag& tag) + { + assert(parentTags.size() == parentIndexes.size()); + + Json::Value* node = &result_; + + if (parentTags.size() != 0) + { + printf("ICI %s\n", FormatTag(parentTags[0]).c_str()); + } + + for (size_t i = 0; i < parentTags.size(); i++) + { + std::string t = FormatTag(parentTags[i]); + + if (!node->isMember(t)) + { + Json::Value item = Json::objectValue; + item["vr"] = "SQ"; + item["Value"] = Json::arrayValue; + item["Value"].append(Json::objectValue); + (*node) [t] = item; + + node = &(*node)[t]["Value"][0]; + std::cout << result_.toStyledString(); + } + else if ((*node) [t].type() != Json::objectValue || + !(*node) [t].isMember("vr") || + (*node) [t]["vr"].type() != Json::stringValue || + (*node) [t]["vr"].asString() != "SQ" || + !(*node) [t].isMember("Value") || + (*node) [t]["Value"].type() != Json::arrayValue) + { + throw OrthancException(ErrorCode_InternalError); + } + else + { + std::cout << result_.toStyledString(); + printf("%d %d\n", (*node) [t]["Value"].size(), parentIndexes[i]); + + if ((*node) [t]["Value"].size() >= parentIndexes[i]) + { + throw OrthancException(ErrorCode_InternalError); + } + else + { + (*node) [t]["Value"].append(Json::objectValue); + node = &(*node) [t]["Value"][Json::ArrayIndex(parentIndexes[i])]; + } + } + } + + assert(node->type() == Json::objectValue); + + std::string t = FormatTag(tag); + if (node->isMember(t)) + { + throw OrthancException(ErrorCode_InternalError); + } + else + { + (*node) [t] = Json::objectValue; + return (*node) [t]; + } + } + + public: + DicomJsonVisitor() + { + Clear(); + } + + void SetBulkUriRoot(const std::string& root) + { + bulkUriRoot_ = root; + } + + void Clear() + { + result_ = Json::objectValue; + } + + const Json::Value& GetResult() const + { + return result_; + } + + virtual void VisitUnknown(const std::vector<DicomTag>& parentTags, + const std::vector<size_t>& parentIndexes, + const DicomTag& tag, + ValueRepresentation vr) ORTHANC_OVERRIDE + { + } + + virtual void VisitBinary(const std::vector<DicomTag>& parentTags, + const std::vector<size_t>& parentIndexes, + const DicomTag& tag, + ValueRepresentation vr, + const void* data, + size_t size) ORTHANC_OVERRIDE + { + if (!bulkUriRoot_.empty()) + { + Json::Value& node = CreateNode(parentTags, parentIndexes, tag); + } + } + + virtual void VisitInteger(const std::vector<DicomTag>& parentTags, + const std::vector<size_t>& parentIndexes, + const DicomTag& tag, + ValueRepresentation vr, + int64_t value) ORTHANC_OVERRIDE + { + Json::Value& node = CreateNode(parentTags, parentIndexes, tag); + + } + + virtual void VisitDouble(const std::vector<DicomTag>& parentTags, + const std::vector<size_t>& parentIndexes, + const DicomTag& tag, + ValueRepresentation vr, + double value) ORTHANC_OVERRIDE + { + Json::Value& node = CreateNode(parentTags, parentIndexes, tag); + + } + + virtual void VisitAttribute(const std::vector<DicomTag>& parentTags, + const std::vector<size_t>& parentIndexes, + const DicomTag& tag, + ValueRepresentation vr, + const DicomTag& value) ORTHANC_OVERRIDE + { + Json::Value& node = CreateNode(parentTags, parentIndexes, tag); + + } + + virtual Action VisitString(std::string& newValue, + const std::vector<DicomTag>& parentTags, + const std::vector<size_t>& parentIndexes, + const DicomTag& tag, + ValueRepresentation vr, + const std::string& value) ORTHANC_OVERRIDE + { + printf("[%s] [%s]\n", FormatTag(tag).c_str(), value.c_str()); + + Json::Value& node = CreateNode(parentTags, parentIndexes, tag); + + return Action_None; + } + }; +} + +#include "../Core/SystemToolbox.h" + + +TEST(DicomWebJson, Basic) +{ + std::string content; + Orthanc::SystemToolbox::ReadFile(content, "/home/jodogne/Subversion/orthanc-tests/Database/DummyCT.dcm"); + + Orthanc::ParsedDicomFile dicom(content); + + Orthanc::DicomJsonVisitor visitor; + dicom.Apply(visitor); + + std::cout << visitor.GetResult().toStyledString() << std::endl; +} + +#endif
--- a/UnitTestsSources/ServerIndexTests.cpp Fri Feb 01 09:28:12 2019 +0100 +++ b/UnitTestsSources/ServerIndexTests.cpp Mon Feb 04 12:06:19 2019 +0100 @@ -293,8 +293,8 @@ ASSERT_EQ("e", l.front()); } - std::list<MetadataType> md; - index_->ListAvailableMetadata(md, a[4]); + std::map<MetadataType, std::string> md; + index_->GetAllMetadata(md, a[4]); ASSERT_EQ(0u, md.size()); index_->AddAttachment(a[4], FileInfo("my json file", FileContentType_DicomAsJson, 42, "md5", @@ -303,11 +303,11 @@ index_->AddAttachment(a[6], FileInfo("world", FileContentType_Dicom, 44, "md5")); index_->SetMetadata(a[4], MetadataType_Instance_RemoteAet, "PINNACLE"); - index_->ListAvailableMetadata(md, a[4]); + index_->GetAllMetadata(md, a[4]); ASSERT_EQ(1u, md.size()); - ASSERT_EQ(MetadataType_Instance_RemoteAet, md.front()); + ASSERT_EQ("PINNACLE", md[MetadataType_Instance_RemoteAet]); index_->SetMetadata(a[4], MetadataType_ModifiedFrom, "TUTU"); - index_->ListAvailableMetadata(md, a[4]); + index_->GetAllMetadata(md, a[4]); ASSERT_EQ(2u, md.size()); std::map<MetadataType, std::string> md2; @@ -317,9 +317,9 @@ ASSERT_EQ("PINNACLE", md2[MetadataType_Instance_RemoteAet]); index_->DeleteMetadata(a[4], MetadataType_ModifiedFrom); - index_->ListAvailableMetadata(md, a[4]); + index_->GetAllMetadata(md, a[4]); ASSERT_EQ(1u, md.size()); - ASSERT_EQ(MetadataType_Instance_RemoteAet, md.front()); + ASSERT_EQ("PINNACLE", md[MetadataType_Instance_RemoteAet]); index_->GetAllMetadata(md2, a[4]); ASSERT_EQ(1u, md2.size());