Mercurial > hg > orthanc
view OrthancServer/OrthancFindRequestHandler.cpp @ 608:0bedf8ff9288 find-move-scp
basic find scp
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Thu, 17 Oct 2013 18:07:55 +0200 |
parents | c931ac02db82 |
children | 5ba825b87b21 |
line wrap: on
line source
/** * Orthanc - A Lightweight, RESTful DICOM Store * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, * 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 "OrthancFindRequestHandler.h" #include <glog/logging.h> #include <boost/regex.hpp> #include "../Core/DicomFormat/DicomArray.h" #include "ServerToolbox.h" namespace Orthanc { static bool ApplyRangeConstraint(const std::string& value, const std::string& constraint) { // TODO return false; } static bool ApplyListConstraint(const std::string& value, const std::string& constraint) { std::cout << value << std::endl; std::string v1 = value; Toolbox::ToLowerCase(v1); std::vector<std::string> items; Toolbox::TokenizeString(items, constraint, '\\'); for (size_t i = 0; i < items.size(); i++) { Toolbox::ToLowerCase(items[i]); if (items[i] == v1) { return true; } } return false; } static bool Matches(const std::string& value, const std::string& constraint) { // http://www.itk.org/Wiki/DICOM_QueryRetrieve_Explained // http://dicomiseasy.blogspot.be/2012/01/dicom-queryretrieve-part-i.html if (constraint.find('-') != std::string::npos) { return ApplyRangeConstraint(value, constraint); } if (constraint.find('\\') != std::string::npos) { return ApplyListConstraint(value, constraint); } if (constraint.find('*') != std::string::npos || constraint.find('?') != std::string::npos) { // TODO - Cache the constructed regular expression boost::regex pattern(Toolbox::WildcardToRegularExpression(constraint), boost::regex::icase /* case insensitive search */); return boost::regex_match(value, pattern); } else { std::string v1 = value; std::string v2 = constraint; Toolbox::ToLowerCase(v1); Toolbox::ToLowerCase(v2); return v1 == v2; } } static bool LookupOneInstance(std::string& result, ServerIndex& index, const std::string& id, ResourceType type) { if (type == ResourceType_Instance) { result = id; return true; } std::string childId; { std::list<std::string> children; index.GetChildInstances(children, id); if (children.size() == 0) { return false; } childId = children.front(); } return LookupOneInstance(result, index, childId, GetChildResourceType(type)); } static bool Matches(const Json::Value& resource, const DicomArray& query) { for (size_t i = 0; i < query.GetSize(); i++) { if (query.GetElement(i).GetValue().IsNull() || query.GetElement(i).GetTag() == DICOM_TAG_QUERY_RETRIEVE_LEVEL || query.GetElement(i).GetTag() == DICOM_TAG_SPECIFIC_CHARACTER_SET) { continue; } std::string tag = query.GetElement(i).GetTag().Format(); std::cout << tag << std::endl; std::string value; if (resource.isMember(tag)) { value = resource.get(tag, Json::arrayValue).get("Value", "").asString(); } if (!Matches(value, query.GetElement(i).GetValue().AsString())) { return false; } } return true; } static void AddAnswer(DicomFindAnswers& answers, const Json::Value& resource, const DicomArray& query) { DicomMap result; for (size_t i = 0; i < query.GetSize(); i++) { if (query.GetElement(i).GetTag() != DICOM_TAG_QUERY_RETRIEVE_LEVEL && query.GetElement(i).GetTag() != DICOM_TAG_SPECIFIC_CHARACTER_SET) { std::string tag = query.GetElement(i).GetTag().Format(); std::string value; if (resource.isMember(tag)) { value = resource.get(tag, Json::arrayValue).get("Value", "").asString(); result.SetValue(query.GetElement(i).GetTag(), value); } } } answers.Add(result); } void OrthancFindRequestHandler::Handle(const DicomMap& input, DicomFindAnswers& answers) { LOG(WARNING) << "Find-SCU request received"; /** * Retrieve the query level. **/ const DicomValue* levelTmp = input.TestAndGetValue(DICOM_TAG_QUERY_RETRIEVE_LEVEL); if (levelTmp == NULL) { throw OrthancException(ErrorCode_BadRequest); } ResourceType level = StringToResourceType(levelTmp->AsString().c_str()); if (level != ResourceType_Patient && level != ResourceType_Study && level != ResourceType_Series) { throw OrthancException(ErrorCode_NotImplemented); } /** * Retrieve all the resources for this query level. **/ Json::Value resources; context_.GetIndex().GetAllUuids(resources, level); assert(resources.type() == Json::arrayValue); // TODO : Speed up using MainDicomTags (to avoid looping over ALL // the resources and reading the JSON file for each of them) /** * Loop over all the resources for this query level. **/ DicomArray query(input); for (Json::Value::ArrayIndex i = 0; i < resources.size(); i++) { try { std::string instance; if (LookupOneInstance(instance, context_.GetIndex(), resources[i].asString(), level)) { Json::Value resource; context_.ReadJson(resource, instance); if (Matches(resource, query)) { AddAnswer(answers, resource, query); } } } catch (OrthancException&) { // This resource has been deleted during the find request } } } }