# HG changeset patch # User Sebastien Jodogne # Date 1527517817 -7200 # Node ID c691fcf66071ea5c316964e034f45dadc1429672 # Parent 75a404e40323c33211fdfdc1d061142f7f79ac26 ResourceModificationJob diff -r 75a404e40323 -r c691fcf66071 CMakeLists.txt --- a/CMakeLists.txt Mon May 28 14:39:22 2018 +0200 +++ b/CMakeLists.txt Mon May 28 16:30:17 2018 +0200 @@ -55,6 +55,7 @@ set(ORTHANC_SERVER_SOURCES OrthancServer/DatabaseWrapper.cpp OrthancServer/DatabaseWrapperBase.cpp + OrthancServer/DicomInstanceOrigin.cpp OrthancServer/DicomInstanceToStore.cpp OrthancServer/ExportedResource.cpp OrthancServer/LuaScripting.cpp diff -r 75a404e40323 -r c691fcf66071 Core/JobsEngine/SetOfInstancesJob.cpp --- a/Core/JobsEngine/SetOfInstancesJob.cpp Mon May 28 14:39:22 2018 +0200 +++ b/Core/JobsEngine/SetOfInstancesJob.cpp Mon May 28 16:30:17 2018 +0200 @@ -178,6 +178,14 @@ } + void SetOfInstancesJob::GetPublicContent(Json::Value& value) + { + value["Description"] = GetDescription(); + value["InstancesCount"] = static_cast(GetInstances().size()); + value["FailedInstancesCount"] = static_cast(GetFailedInstances().size()); + } + + void SetOfInstancesJob::GetInternalContent(Json::Value& value) { Json::Value v = Json::arrayValue; diff -r 75a404e40323 -r c691fcf66071 Core/JobsEngine/SetOfInstancesJob.h --- a/Core/JobsEngine/SetOfInstancesJob.h Mon May 28 14:39:22 2018 +0200 +++ b/Core/JobsEngine/SetOfInstancesJob.h Mon May 28 16:30:17 2018 +0200 @@ -107,6 +107,8 @@ virtual JobStepResult ExecuteStep(); + virtual void GetPublicContent(Json::Value& value); + virtual void GetInternalContent(Json::Value& value); }; } diff -r 75a404e40323 -r c691fcf66071 OrthancServer/DicomInstanceOrigin.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/DicomInstanceOrigin.cpp Mon May 28 16:30:17 2018 +0200 @@ -0,0 +1,134 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2018 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 . + **/ + + +#include "PrecompiledHeadersServer.h" +#include "DicomInstanceOrigin.h" + +#include "../Core/OrthancException.h" + + +namespace Orthanc +{ + void DicomInstanceOrigin::Format(Json::Value& result) const + { + result = Json::objectValue; + result["RequestOrigin"] = EnumerationToString(origin_); + + switch (origin_) + { + case RequestOrigin_Unknown: + { + // None of the methods "SetDicomProtocolOrigin()", "SetHttpOrigin()", + // "SetLuaOrigin()" or "SetPluginsOrigin()" was called! + throw OrthancException(ErrorCode_BadSequenceOfCalls); + } + + case RequestOrigin_DicomProtocol: + { + result["RemoteIp"] = remoteIp_; + result["RemoteAet"] = dicomRemoteAet_; + result["CalledAet"] = dicomCalledAet_; + break; + } + + case RequestOrigin_RestApi: + { + result["RemoteIp"] = remoteIp_; + result["Username"] = httpUsername_; + break; + } + + case RequestOrigin_Lua: + case RequestOrigin_Plugins: + { + // No additional information available for these kinds of requests + break; + } + + default: + throw OrthancException(ErrorCode_InternalError); + } + } + + + void DicomInstanceOrigin::SetDicomProtocolOrigin(const char* remoteIp, + const char* remoteAet, + const char* calledAet) + { + origin_ = RequestOrigin_DicomProtocol; + remoteIp_ = remoteIp; + dicomRemoteAet_ = remoteAet; + dicomCalledAet_ = calledAet; + } + + void DicomInstanceOrigin::SetRestOrigin(const RestApiCall& call) + { + origin_ = call.GetRequestOrigin(); + + if (origin_ == RequestOrigin_RestApi) + { + remoteIp_ = call.GetRemoteIp(); + httpUsername_ = call.GetUsername(); + } + } + + void DicomInstanceOrigin::SetHttpOrigin(const char* remoteIp, + const char* username) + { + origin_ = RequestOrigin_RestApi; + remoteIp_ = remoteIp; + httpUsername_ = username; + } + + void DicomInstanceOrigin::SetLuaOrigin() + { + origin_ = RequestOrigin_Lua; + } + + void DicomInstanceOrigin::SetPluginsOrigin() + { + origin_ = RequestOrigin_Plugins; + } + + const char* DicomInstanceOrigin::GetRemoteAet() const + { + if (origin_ == RequestOrigin_DicomProtocol) + { + return dicomRemoteAet_.c_str(); + } + else + { + return ""; + } + } +} diff -r 75a404e40323 -r c691fcf66071 OrthancServer/DicomInstanceOrigin.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/DicomInstanceOrigin.h Mon May 28 16:30:17 2018 +0200 @@ -0,0 +1,77 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2018 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 . + **/ + + +#pragma once + +#include "../Core/RestApi/RestApiCall.h" + +namespace Orthanc +{ + class DicomInstanceOrigin + { + private: + RequestOrigin origin_; + std::string remoteIp_; + std::string dicomRemoteAet_; + std::string dicomCalledAet_; + std::string httpUsername_; + + public: + DicomInstanceOrigin() : + origin_(RequestOrigin_Unknown) + { + } + + void SetDicomProtocolOrigin(const char* remoteIp, + const char* remoteAet, + const char* calledAet); + + void SetRestOrigin(const RestApiCall& call); + + void SetHttpOrigin(const char* remoteIp, + const char* username); + + void SetLuaOrigin(); + + void SetPluginsOrigin(); + + RequestOrigin GetRequestOrigin() const + { + return origin_; + } + + const char* GetRemoteAet() const; + + void Format(Json::Value& result) const; + }; +} diff -r 75a404e40323 -r c691fcf66071 OrthancServer/DicomInstanceToStore.cpp --- a/OrthancServer/DicomInstanceToStore.cpp Mon May 28 14:39:22 2018 +0200 +++ b/OrthancServer/DicomInstanceToStore.cpp Mon May 28 16:30:17 2018 +0200 @@ -181,101 +181,6 @@ } - - void DicomInstanceToStore::GetOriginInformation(Json::Value& result) const - { - result = Json::objectValue; - result["RequestOrigin"] = EnumerationToString(origin_); - - switch (origin_) - { - case RequestOrigin_Unknown: - { - // None of the methods "SetDicomProtocolOrigin()", "SetHttpOrigin()", - // "SetLuaOrigin()" or "SetPluginsOrigin()" was called! - throw OrthancException(ErrorCode_BadSequenceOfCalls); - } - - case RequestOrigin_DicomProtocol: - { - result["RemoteIp"] = remoteIp_; - result["RemoteAet"] = dicomRemoteAet_; - result["CalledAet"] = dicomCalledAet_; - break; - } - - case RequestOrigin_RestApi: - { - result["RemoteIp"] = remoteIp_; - result["Username"] = httpUsername_; - break; - } - - case RequestOrigin_Lua: - case RequestOrigin_Plugins: - { - // No additional information available for these kinds of requests - break; - } - - default: - throw OrthancException(ErrorCode_InternalError); - } - } - - - void DicomInstanceToStore::SetDicomProtocolOrigin(const char* remoteIp, - const char* remoteAet, - const char* calledAet) - { - origin_ = RequestOrigin_DicomProtocol; - remoteIp_ = remoteIp; - dicomRemoteAet_ = remoteAet; - dicomCalledAet_ = calledAet; - } - - void DicomInstanceToStore::SetRestOrigin(const RestApiCall& call) - { - origin_ = call.GetRequestOrigin(); - - if (origin_ == RequestOrigin_RestApi) - { - remoteIp_ = call.GetRemoteIp(); - httpUsername_ = call.GetUsername(); - } - } - - void DicomInstanceToStore::SetHttpOrigin(const char* remoteIp, - const char* username) - { - origin_ = RequestOrigin_RestApi; - remoteIp_ = remoteIp; - httpUsername_ = username; - } - - void DicomInstanceToStore::SetLuaOrigin() - { - origin_ = RequestOrigin_Lua; - } - - void DicomInstanceToStore::SetPluginsOrigin() - { - origin_ = RequestOrigin_Plugins; - } - - const char* DicomInstanceToStore::GetRemoteAet() const - { - if (origin_ == RequestOrigin_DicomProtocol) - { - return dicomRemoteAet_.c_str(); - } - else - { - return ""; - } - } - - bool DicomInstanceToStore::LookupTransferSyntax(std::string& result) { ComputeMissingInformation(); diff -r 75a404e40323 -r c691fcf66071 OrthancServer/DicomInstanceToStore.h --- a/OrthancServer/DicomInstanceToStore.h Mon May 28 14:39:22 2018 +0200 +++ b/OrthancServer/DicomInstanceToStore.h Mon May 28 16:30:17 2018 +0200 @@ -34,9 +34,9 @@ #pragma once #include "../Core/DicomParsing/ParsedDicomFile.h" +#include "../Core/OrthancException.h" +#include "DicomInstanceOrigin.h" #include "ServerIndex.h" -#include "../Core/OrthancException.h" -#include "../Core/RestApi/RestApiCall.h" namespace Orthanc { @@ -139,46 +139,31 @@ } }; - - SmartContainer buffer_; + DicomInstanceOrigin origin_; + SmartContainer buffer_; SmartContainer parsed_; - SmartContainer summary_; - SmartContainer json_; - - RequestOrigin origin_; - std::string remoteIp_; - std::string dicomRemoteAet_; - std::string dicomCalledAet_; - std::string httpUsername_; - ServerIndex::MetadataMap metadata_; + SmartContainer summary_; + SmartContainer json_; + ServerIndex::MetadataMap metadata_; void ComputeMissingInformation(); public: - DicomInstanceToStore() : origin_(RequestOrigin_Unknown) + void SetOrigin(const DicomInstanceOrigin& origin) { + origin_ = origin; } - - void SetDicomProtocolOrigin(const char* remoteIp, - const char* remoteAet, - const char* calledAet); - - void SetRestOrigin(const RestApiCall& call); - - void SetHttpOrigin(const char* remoteIp, - const char* username); - - void SetLuaOrigin(); - - void SetPluginsOrigin(); - - RequestOrigin GetRequestOrigin() const + + DicomInstanceOrigin& GetOrigin() { return origin_; } - - const char* GetRemoteAet() const; - + + const DicomInstanceOrigin& GetOrigin() const + { + return origin_; + } + void SetBuffer(const std::string& dicom) { buffer_.SetConstReference(dicom); @@ -221,8 +206,6 @@ const Json::Value& GetJson(); - void GetOriginInformation(Json::Value& result) const; - bool LookupTransferSyntax(std::string& result); }; } diff -r 75a404e40323 -r c691fcf66071 OrthancServer/LuaScripting.cpp --- a/OrthancServer/LuaScripting.cpp Mon May 28 14:39:22 2018 +0200 +++ b/OrthancServer/LuaScripting.cpp Mon May 28 16:30:17 2018 +0200 @@ -71,7 +71,7 @@ simplifiedTags_(simplifiedTags), metadata_(metadata) { - instance.GetOriginInformation(origin_); + instance.GetOrigin().Format(origin_); } virtual void Apply(LuaScripting& that) @@ -653,7 +653,7 @@ call.PushJson(simplified); Json::Value origin; - instance.GetOriginInformation(origin); + instance.GetOrigin().Format(origin); call.PushJson(origin); if (!call.ExecutePredicate()) diff -r 75a404e40323 -r c691fcf66071 OrthancServer/OrthancRestApi/OrthancRestAnonymizeModify.cpp --- a/OrthancServer/OrthancRestApi/OrthancRestAnonymizeModify.cpp Mon May 28 14:39:22 2018 +0200 +++ b/OrthancServer/OrthancRestApi/OrthancRestAnonymizeModify.cpp Mon May 28 16:30:17 2018 +0200 @@ -54,14 +54,39 @@ } + static int GetPriority(const Json::Value& request) + { + static const char* PRIORITY = "Priority"; + + if (request.isMember(PRIORITY)) + { + if (request[PRIORITY].type() == Json::intValue) + { + return request[PRIORITY].asInt(); + } + else + { + LOG(ERROR) << "Field \"" << PRIORITY << "\" of a modification request should be an integer"; + throw OrthancException(ErrorCode_BadFileFormat); + } + } + else + { + return 0; // Default priority + } + } + + static void ParseModifyRequest(DicomModification& target, + int& priority, const RestApiPostCall& call) { - // curl http://localhost:8042/series/95a6e2bf-9296e2cc-bf614e2f-22b391ee-16e010e0/modify -X POST -d '{"Replace":{"InstitutionName":"My own clinic"}}' + // curl http://localhost:8042/series/95a6e2bf-9296e2cc-bf614e2f-22b391ee-16e010e0/modify -X POST -d '{"Replace":{"InstitutionName":"My own clinic"},"Priority":9}' Json::Value request; if (call.ParseJsonRequest(request)) { + priority = GetPriority(request); target.ParseModifyRequest(request); } else @@ -72,6 +97,7 @@ static void ParseAnonymizationRequest(DicomModification& target, + int& priority, RestApiPostCall& call) { // curl http://localhost:8042/instances/6e67da51-d119d6ae-c5667437-87b9a8a5-0f07c49f/anonymize -X POST -d '{"Replace":{"PatientName":"hello","0010-0020":"world"},"Keep":["StudyDescription", "SeriesDescription"],"KeepPrivateTags": true,"Remove":["Modality"]}' > Anonymized.dcm @@ -80,6 +106,8 @@ if (call.ParseJsonRequest(request) && request.isObject()) { + priority = GetPriority(request); + bool patientNameReplaced; target.ParseAnonymizationRequest(patientNameReplaced, request); @@ -110,53 +138,132 @@ } - static void AnonymizeOrModifyResource(DicomModification* modificationRaw, // Takes ownership - MetadataType metadataType, - ResourceType resourceType, - RestApiPostCall& call) + + class ResourceModificationJob : public SetOfInstancesJob { - if (modificationRaw == NULL) + public: + class Output : public boost::noncopyable { - throw OrthancException(ErrorCode_NullPointer); - } - - std::auto_ptr modification(modificationRaw); - - bool isFirst = true; - Json::Value result(Json::objectValue); + private: + boost::mutex mutex_; + ResourceType level_; + bool isFirst_; + std::string id_; + std::string patientId_; + + public: + Output(ResourceType level) : + level_(level), + isFirst_(true) + { + if (level_ != ResourceType_Patient && + level_ != ResourceType_Study && + level_ != ResourceType_Series) + { + throw OrthancException(ErrorCode_ParameterOutOfRange); + } + } - ServerContext& context = OrthancRestApi::GetContext(call); + ResourceType GetLevel() const + { + return level_; + } + + void Update(DicomInstanceHasher& hasher) + { + boost::mutex::scoped_lock lock(mutex_); + + if (isFirst_) + { + switch (level_) + { + case ResourceType_Series: + id_ = hasher.HashSeries(); + break; + + case ResourceType_Study: + id_ = hasher.HashStudy(); + break; + + case ResourceType_Patient: + id_ = hasher.HashPatient(); + break; + + default: + throw OrthancException(ErrorCode_InternalError); + } - typedef std::list Instances; - Instances instances; - std::string id = call.GetUriComponent("id", ""); - context.GetIndex().GetChildInstances(instances, id); + patientId_ = hasher.HashPatient(); + isFirst_ = false; + } + } - if (instances.empty()) - { - return; - } + bool Format(Json::Value& target) + { + boost::mutex::scoped_lock lock(mutex_); + + if (isFirst_) + { + return false; + } + else + { + target = Json::objectValue; + target["Type"] = EnumerationToString(level_); + target["ID"] = id_; + target["Path"] = GetBasePath(level_, id_); + target["PatientID"] = patientId_; + return true; + } + } - - /** - * Loop over all the instances of the resource. - **/ + bool GetIdentifier(std::string& id) + { + boost::mutex::scoped_lock lock(mutex_); + + if (isFirst_) + { + return false; + } + else + { + id = id_; + return true; + } + } + }; + + private: + ServerContext& context_; + std::auto_ptr modification_; + boost::shared_ptr output_; + bool isAnonymization_; + MetadataType metadataType_; + std::string description_; + DicomInstanceOrigin origin_; - for (Instances::const_iterator it = instances.begin(); - it != instances.end(); ++it) + protected: + bool HandleInstance(const std::string& instance) { - LOG(INFO) << "Modifying instance " << *it; + if (modification_.get() == NULL) + { + LOG(ERROR) << "No modification was provided for this job"; + throw OrthancException(ErrorCode_BadSequenceOfCalls); + } + + + LOG(INFO) << "Modifying instance in a job: " << instance; std::auto_ptr locker; try { - locker.reset(new ServerContext::DicomCacheLocker(OrthancRestApi::GetContext(call), *it)); + locker.reset(new ServerContext::DicomCacheLocker(context_, instance)); } catch (OrthancException&) { - // This child instance has been removed in between - continue; + LOG(WARNING) << "An instance was removed after the job was issued: " << instance; + return false; } @@ -169,10 +276,10 @@ **/ std::auto_ptr modified(original.Clone(true)); - modification->Apply(*modified); + modification_->Apply(*modified); DicomInstanceToStore toStore; - toStore.SetRestOrigin(call); + toStore.SetOrigin(origin_); toStore.SetParsedDicomFile(*modified); @@ -182,6 +289,10 @@ **/ DicomInstanceHasher modifiedHasher = modified->GetHasher(); + + MetadataType metadataType = (isAnonymization_ ? + MetadataType_AnonymizedFrom : + MetadataType_ModifiedFrom); if (originalHasher.HashSeries() != modifiedHasher.HashSeries()) { @@ -198,8 +309,8 @@ toStore.AddMetadata(ResourceType_Patient, metadataType, originalHasher.HashPatient()); } - assert(*it == originalHasher.HashInstance()); - toStore.AddMetadata(ResourceType_Instance, metadataType, *it); + assert(instance == originalHasher.HashInstance()); + toStore.AddMetadata(ResourceType_Instance, metadataType, instance); /** @@ -207,9 +318,9 @@ **/ std::string modifiedInstance; - if (context.Store(modifiedInstance, toStore) != StoreStatus_Success) + if (context_.Store(modifiedInstance, toStore) != StoreStatus_Success) { - LOG(ERROR) << "Error while storing a modified instance " << *it; + LOG(ERROR) << "Error while storing a modified instance " << instance; throw OrthancException(ErrorCode_CannotStoreInstance); } @@ -217,41 +328,127 @@ assert(modifiedInstance == modifiedHasher.HashInstance()); - /** - * Compute the JSON object that is returned by the REST call. - **/ - - if (isFirst) + if (output_.get() != NULL) { - std::string newId; + output_->Update(modifiedHasher); + } - switch (resourceType) - { - case ResourceType_Series: - newId = modifiedHasher.HashSeries(); - break; + return true; + } + + public: + ResourceModificationJob(ServerContext& context) : + context_(context), + isAnonymization_(false) + { + } - case ResourceType_Study: - newId = modifiedHasher.HashStudy(); - break; - - case ResourceType_Patient: - newId = modifiedHasher.HashPatient(); - break; + void SetModification(DicomModification* modification, // Takes ownership + bool isAnonymization) + { + if (modification == NULL) + { + throw OrthancException(ErrorCode_NullPointer); + } + else if (IsStarted()) + { + throw OrthancException(ErrorCode_BadSequenceOfCalls); + } + else + { + modification_.reset(modification); + isAnonymization_ = isAnonymization; + } + } - default: - throw OrthancException(ErrorCode_InternalError); - } + void SetOutput(boost::shared_ptr& output) + { + if (IsStarted()) + { + throw OrthancException(ErrorCode_BadSequenceOfCalls); + } + else + { + output_ = output; + } + } - result["Type"] = EnumerationToString(resourceType); - result["ID"] = newId; - result["Path"] = GetBasePath(resourceType, newId); - result["PatientID"] = modifiedHasher.HashPatient(); - isFirst = false; + void SetOrigin(const DicomInstanceOrigin& origin) + { + if (IsStarted()) + { + throw OrthancException(ErrorCode_BadSequenceOfCalls); + } + else + { + origin_ = origin; } } - call.GetOutput().AnswerJson(result); + void SetOrigin(const RestApiCall& call) + { + DicomInstanceOrigin tmp; + tmp.SetRestOrigin(call); + SetOrigin(tmp); + } + + virtual void ReleaseResources() + { + } + + virtual void GetJobType(std::string& target) + { + target = "ResourceModification"; + } + + virtual void GetPublicContent(Json::Value& value) + { + SetOfInstancesJob::GetPublicContent(value); + + value["IsAnonymization"] = isAnonymization_; + } + + virtual void GetInternalContent(Json::Value& value) + { + SetOfInstancesJob::GetInternalContent(value); + + Json::Value tmp; + modification_->Serialize(tmp); + value["Modification"] = tmp; + } + }; + + + + static void SubmitJob(std::auto_ptr& modification, + bool isAnonymization, + ResourceType level, + int priority, + RestApiPostCall& call) + { + ServerContext& context = OrthancRestApi::GetContext(call); + + std::auto_ptr job(new ResourceModificationJob(context)); + + boost::shared_ptr output(new ResourceModificationJob::Output(level)); + job->SetModification(modification.release(), isAnonymization); + job->SetOutput(output); + job->SetOrigin(call); + job->SetDescription("REST API"); + + context.AddChildInstances(*job, call.GetUriComponent("id", "")); + + if (context.GetJobsEngine().GetRegistry().SubmitAndWait(job.release(), priority)) + { + Json::Value json; + if (output->Format(json)) + { + call.GetOutput().AnswerJson(json); + return; + } + } + + call.GetOutput().SignalError(HttpStatus_500_InternalServerError); } @@ -261,7 +458,8 @@ DicomModification modification; modification.SetAllowManualIdentifiers(true); - ParseModifyRequest(modification, call); + int priority; + ParseModifyRequest(modification, priority, call); if (modification.IsReplaced(DICOM_TAG_PATIENT_ID)) { @@ -289,7 +487,8 @@ DicomModification modification; modification.SetAllowManualIdentifiers(true); - ParseAnonymizationRequest(modification, call); + int priority; + ParseAnonymizationRequest(modification, priority, call); AnonymizeOrModifyInstance(modification, call); } @@ -299,10 +498,12 @@ static void ModifyResource(RestApiPostCall& call) { std::auto_ptr modification(new DicomModification); - ParseModifyRequest(*modification, call); + + int priority; + ParseModifyRequest(*modification, priority, call); modification->SetLevel(resourceType); - AnonymizeOrModifyResource(modification.release(), MetadataType_ModifiedFrom, resourceType, call); + SubmitJob(modification, false, resourceType, priority, call); } @@ -310,9 +511,11 @@ static void AnonymizeResource(RestApiPostCall& call) { std::auto_ptr modification(new DicomModification); - ParseAnonymizationRequest(*modification, call); - AnonymizeOrModifyResource(modification.release(), MetadataType_AnonymizedFrom, resourceType, call); + int priority; + ParseAnonymizationRequest(*modification, priority, call); + + SubmitJob(modification, true, resourceType, priority, call); } @@ -321,7 +524,7 @@ ParsedDicomFile& dicom) { DicomInstanceToStore toStore; - toStore.SetRestOrigin(call); + toStore.GetOrigin().SetRestOrigin(call); toStore.SetParsedDicomFile(dicom); ServerContext& context = OrthancRestApi::GetContext(call); diff -r 75a404e40323 -r c691fcf66071 OrthancServer/OrthancRestApi/OrthancRestApi.cpp --- a/OrthancServer/OrthancRestApi/OrthancRestApi.cpp Mon May 28 14:39:22 2018 +0200 +++ b/OrthancServer/OrthancRestApi/OrthancRestApi.cpp Mon May 28 16:30:17 2018 +0200 @@ -93,7 +93,7 @@ std::string postData(call.GetBodyData(), call.GetBodySize()); DicomInstanceToStore toStore; - toStore.SetRestOrigin(call); + toStore.GetOrigin().SetRestOrigin(call); toStore.SetBuffer(postData); std::string publicId; diff -r 75a404e40323 -r c691fcf66071 OrthancServer/ServerIndex.cpp --- a/OrthancServer/ServerIndex.cpp Mon May 28 14:39:22 2018 +0200 +++ b/OrthancServer/ServerIndex.cpp Mon May 28 16:30:17 2018 +0200 @@ -778,9 +778,10 @@ // Attach the auto-computed metadata for the instance level, // reflecting these additions into the input metadata map SetInstanceMetadata(instanceMetadata, instance, MetadataType_Instance_ReceptionDate, now); - SetInstanceMetadata(instanceMetadata, instance, MetadataType_Instance_RemoteAet, instanceToStore.GetRemoteAet()); + SetInstanceMetadata(instanceMetadata, instance, MetadataType_Instance_RemoteAet, + instanceToStore.GetOrigin().GetRemoteAet()); SetInstanceMetadata(instanceMetadata, instance, MetadataType_Instance_Origin, - EnumerationToString(instanceToStore.GetRequestOrigin())); + EnumerationToString(instanceToStore.GetOrigin().GetRequestOrigin())); { std::string s; diff -r 75a404e40323 -r c691fcf66071 OrthancServer/ServerJobs/DicomModalityStoreJob.cpp --- a/OrthancServer/ServerJobs/DicomModalityStoreJob.cpp Mon May 28 14:39:22 2018 +0200 +++ b/OrthancServer/ServerJobs/DicomModalityStoreJob.cpp Mon May 28 16:30:17 2018 +0200 @@ -51,6 +51,7 @@ bool DicomModalityStoreJob::HandleInstance(const std::string& instance) { + assert(IsStarted()); OpenConnection(); LOG(INFO) << "Sending instance " << instance << " to modality \"" @@ -170,7 +171,8 @@ void DicomModalityStoreJob::GetPublicContent(Json::Value& value) { - value["Description"] = GetDescription(); + SetOfInstancesJob::GetPublicContent(value); + value["LocalAet"] = localAet_; value["RemoteAet"] = remote_.GetApplicationEntityTitle(); @@ -179,8 +181,5 @@ value["MoveOriginatorAET"] = GetMoveOriginatorAet(); value["MoveOriginatorID"] = GetMoveOriginatorId(); } - - value["InstancesCount"] = static_cast(GetInstances().size()); - value["FailedInstancesCount"] = static_cast(GetFailedInstances().size()); } } diff -r 75a404e40323 -r c691fcf66071 OrthancServer/ServerJobs/ModifyInstanceOperation.cpp --- a/OrthancServer/ServerJobs/ModifyInstanceOperation.cpp Mon May 28 14:39:22 2018 +0200 +++ b/OrthancServer/ServerJobs/ModifyInstanceOperation.cpp Mon May 28 16:30:17 2018 +0200 @@ -105,7 +105,7 @@ DicomInstanceToStore toStore; assert(origin_ == RequestOrigin_Lua); - toStore.SetLuaOrigin(); + toStore.GetOrigin().SetLuaOrigin(); toStore.SetParsedDicomFile(*modified); // TODO other metadata diff -r 75a404e40323 -r c691fcf66071 OrthancServer/ServerJobs/OrthancPeerStoreJob.cpp --- a/OrthancServer/ServerJobs/OrthancPeerStoreJob.cpp Mon May 28 14:39:22 2018 +0200 +++ b/OrthancServer/ServerJobs/OrthancPeerStoreJob.cpp Mon May 28 16:30:17 2018 +0200 @@ -95,12 +95,10 @@ void OrthancPeerStoreJob::GetPublicContent(Json::Value& value) { + SetOfInstancesJob::GetPublicContent(value); + Json::Value v; peer_.ToJson(v); value["Peer"] = v; - - value["Description"] = GetDescription(); - value["InstancesCount"] = static_cast(GetInstances().size()); - value["FailedInstancesCount"] = static_cast(GetFailedInstances().size()); } } diff -r 75a404e40323 -r c691fcf66071 OrthancServer/main.cpp --- a/OrthancServer/main.cpp Mon May 28 14:39:22 2018 +0200 +++ b/OrthancServer/main.cpp Mon May 28 16:30:17 2018 +0200 @@ -75,7 +75,7 @@ if (dicomFile.size() > 0) { DicomInstanceToStore toStore; - toStore.SetDicomProtocolOrigin(remoteIp.c_str(), remoteAet.c_str(), calledAet.c_str()); + toStore.GetOrigin().SetDicomProtocolOrigin(remoteIp.c_str(), remoteAet.c_str(), calledAet.c_str()); toStore.SetBuffer(dicomFile); toStore.SetSummary(dicomSummary); toStore.SetJson(dicomJson); diff -r 75a404e40323 -r c691fcf66071 Plugins/Engine/OrthancPlugins.cpp --- a/Plugins/Engine/OrthancPlugins.cpp Mon May 28 14:39:22 2018 +0200 +++ b/Plugins/Engine/OrthancPlugins.cpp Mon May 28 16:30:17 2018 +0200 @@ -1544,7 +1544,7 @@ switch (service) { case _OrthancPluginService_GetInstanceRemoteAet: - *p.resultString = instance.GetRemoteAet(); + *p.resultString = instance.GetOrigin().GetRemoteAet(); return; case _OrthancPluginService_GetInstanceSize: @@ -1585,7 +1585,7 @@ } case _OrthancPluginService_GetInstanceOrigin: // New in Orthanc 0.9.5 - *p.resultOrigin = Plugins::Convert(instance.GetRequestOrigin()); + *p.resultOrigin = Plugins::Convert(instance.GetOrigin().GetRequestOrigin()); return; default: