Mercurial > hg > orthanc
diff OrthancServer/Plugins/Samples/MultitenantDicom/PluginToolbox.cpp @ 5273:7cb1b851f5c8
Added a sample plugin bringing multitenant DICOM support through labels
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Fri, 14 Apr 2023 11:49:24 +0200 |
parents | |
children | a8385880902f |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/Plugins/Samples/MultitenantDicom/PluginToolbox.cpp Fri Apr 14 11:49:24 2023 +0200 @@ -0,0 +1,207 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2023 Osimis S.A., Belgium + * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/>. + **/ + + +#include "PluginToolbox.h" + +#include "../../../../OrthancFramework/Sources/OrthancException.h" +#include "../../../../OrthancFramework/Sources/SerializationToolbox.h" +#include "../../../../OrthancFramework/Sources/Toolbox.h" + +#include "../Common/OrthancPluginCppWrapper.h" + + +namespace PluginToolbox +{ + bool IsValidLabel(const std::string& label) + { + if (label.empty()) + { + return false; + } + + if (label.size() > 64) + { + // This limitation is for MySQL, which cannot use a TEXT + // column of undefined length as a primary key + return false; + } + + for (size_t i = 0; i < label.size(); i++) + { + if (!(label[i] == '_' || + label[i] == '-' || + (label[i] >= 'a' && label[i] <= 'z') || + (label[i] >= 'A' && label[i] <= 'Z') || + (label[i] >= '0' && label[i] <= '9'))) + { + return false; + } + } + + return true; + } + + + Orthanc::ResourceType ParseQueryRetrieveLevel(const std::string& level) + { + if (level == "PATIENT") + { + return Orthanc::ResourceType_Patient; + } + else if (level == "STUDY") + { + return Orthanc::ResourceType_Study; + } + else if (level == "SERIES") + { + return Orthanc::ResourceType_Series; + } + else if (level == "INSTANCE") + { + return Orthanc::ResourceType_Instance; + } + else + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_NetworkProtocol, "Bad value for QueryRetrieveLevel in DICOM C-FIND: " + level); + } + } + + + bool IsSameAETitle(bool isStrict, + const std::string& aet1, + const std::string& aet2) + { + if (isStrict) + { + // Case-sensitive matching + return aet1 == aet2; + } + else + { + // Case-insensitive matching (default) + std::string tmp1, tmp2; + Orthanc::Toolbox::ToLowerCase(tmp1, aet1); + Orthanc::Toolbox::ToLowerCase(tmp2, aet2); + return tmp1 == tmp2; + } + } + + + bool LookupAETitle(std::string& name, + Orthanc::RemoteModalityParameters& parameters, + bool isStrict, + const std::string& aet) + { + Json::Value modalities; + if (!OrthancPlugins::RestApiGet(modalities, "/modalities?expand", false)) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError, "Unable to obtain the list of the remote modalities"); + } + + std::vector<std::string> names = modalities.getMemberNames(); + for (size_t i = 0; i < names.size(); i++) + { + parameters = Orthanc::RemoteModalityParameters(modalities[names[i]]); + + if (IsSameAETitle(isStrict, parameters.GetApplicationEntityTitle(), aet)) + { + name = names[i]; + return true; + } + } + + return false; + } + + + void ParseLabels(std::set<std::string>& targetLabels, + LabelsConstraint& targetConstraint, + const Json::Value& serverConfig) + { + Orthanc::SerializationToolbox::ReadSetOfStrings(targetLabels, serverConfig, KEY_LABELS); + + for (std::set<std::string>::const_iterator it = targetLabels.begin(); it != targetLabels.end(); ++it) + { + if (!PluginToolbox::IsValidLabel(*it)) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange, "Invalid label: " + *it); + } + } + + std::string s = Orthanc::SerializationToolbox::ReadString(serverConfig, KEY_LABELS_CONSTRAINT, KEY_ALL); + targetConstraint = PluginToolbox::StringToLabelsConstraint(s); + } + + + void AddLabelsToFindRequest(Json::Value& request, + const std::set<std::string>& labels, + LabelsConstraint constraint) + { + Json::Value items = Json::arrayValue; + for (std::set<std::string>::const_iterator it = labels.begin(); it != labels.end(); ++it) + { + items.append(*it); + } + + request[KEY_LABELS] = items; + + switch (constraint) + { + case LabelsConstraint_All: + request[KEY_LABELS_CONSTRAINT] = KEY_ALL; + break; + + case LabelsConstraint_Any: + request[KEY_LABELS_CONSTRAINT] = KEY_ANY; + break; + + case LabelsConstraint_None: + request[KEY_LABELS_CONSTRAINT] = KEY_NONE; + break; + + default: + throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); + } + } + + + LabelsConstraint StringToLabelsConstraint(const std::string& s) + { + if (s == KEY_ALL) + { + return LabelsConstraint_All; + } + else if (s == KEY_ANY) + { + return LabelsConstraint_Any; + } + else if (s == KEY_NONE) + { + return LabelsConstraint_None; + } + else + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange, "Bad value for constraint of labels: " + s); + } + } +}