# HG changeset patch # User Sebastien Jodogne # Date 1539011119 -7200 # Node ID abce036683cd041300021d6a4ff54c15bd681554 # Parent 251614c2edac9fef1fc0f2155a63803d28944a50 sharing code within OrthancRestAnonymizeModify diff -r 251614c2edac -r abce036683cd OrthancServer/OrthancRestApi/OrthancRestAnonymizeModify.cpp --- a/OrthancServer/OrthancRestApi/OrthancRestAnonymizeModify.cpp Mon Oct 08 16:08:51 2018 +0200 +++ b/OrthancServer/OrthancRestApi/OrthancRestAnonymizeModify.cpp Mon Oct 08 17:05:19 2018 +0200 @@ -57,39 +57,14 @@ } - 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, + static void ParseModifyRequest(Json::Value& request, + DicomModification& target, const RestApiPostCall& call) { // 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 @@ -99,18 +74,15 @@ } - static void ParseAnonymizationRequest(DicomModification& target, - int& priority, + static void ParseAnonymizationRequest(Json::Value& request, + DicomModification& target, 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 - Json::Value request; if (call.ParseJsonRequest(request) && request.isObject()) { - priority = GetPriority(request); - bool patientNameReplaced; target.ParseAnonymizationRequest(patientNameReplaced, request); @@ -145,49 +117,13 @@ } - - 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", "")); - - Json::Value publicContent; - if (context.GetJobsEngine().GetRegistry().SubmitAndWait - (publicContent, job.release(), priority)) - { - Json::Value json; - if (output->Format(json)) - { - call.GetOutput().AnswerJson(json); - return; - } - } - - call.GetOutput().SignalError(HttpStatus_500_InternalServerError); - } - - - static void ModifyInstance(RestApiPostCall& call) { DicomModification modification; modification.SetAllowManualIdentifiers(true); - int priority; - ParseModifyRequest(modification, priority, call); + Json::Value request; + ParseModifyRequest(request, modification, call); if (modification.IsReplaced(DICOM_TAG_PATIENT_ID)) { @@ -215,23 +151,45 @@ DicomModification modification; modification.SetAllowManualIdentifiers(true); - int priority; - ParseAnonymizationRequest(modification, priority, call); + Json::Value request; + ParseAnonymizationRequest(request, modification, call); AnonymizeOrModifyInstance(modification, call); } + static void SubmitModificationJob(std::auto_ptr& modification, + bool isAnonymization, + RestApiPostCall& call, + const Json::Value& body, + ResourceType level) + { + ServerContext& context = OrthancRestApi::GetContext(call); + + std::auto_ptr job(new ResourceModificationJob(context)); + + job->SetModification(modification.release(), level, isAnonymization); + job->SetOrigin(call); + + context.AddChildInstances(*job, call.GetUriComponent("id", "")); + + OrthancRestApi::GetApi(call).SubmitCommandsJob + (call, job.release(), true /* synchronous by default */, body); + } + + template static void ModifyResource(RestApiPostCall& call) { std::auto_ptr modification(new DicomModification); - int priority; - ParseModifyRequest(*modification, priority, call); + Json::Value body; + ParseModifyRequest(body, *modification, call); modification->SetLevel(resourceType); - SubmitJob(modification, false, resourceType, priority, call); + + SubmitModificationJob(modification, false /* not an anonymization */, + call, body, resourceType); } @@ -240,10 +198,11 @@ { std::auto_ptr modification(new DicomModification); - int priority; - ParseAnonymizationRequest(*modification, priority, call); + Json::Value body; + ParseAnonymizationRequest(body, *modification, call); - SubmitJob(modification, true, resourceType, priority, call); + SubmitModificationJob(modification, true /* anonymization */, + call, body, resourceType); } diff -r 251614c2edac -r abce036683cd OrthancServer/OrthancRestApi/OrthancRestModalities.cpp --- a/OrthancServer/OrthancRestApi/OrthancRestModalities.cpp Mon Oct 08 16:08:51 2018 +0200 +++ b/OrthancServer/OrthancRestApi/OrthancRestModalities.cpp Mon Oct 08 17:05:19 2018 +0200 @@ -721,50 +721,6 @@ } - static void SubmitJob(RestApiPostCall& call, - const Json::Value& request, - SetOfInstancesJob* jobRaw) - { - std::auto_ptr job(jobRaw); - - if (job.get() == NULL) - { - throw OrthancException(ErrorCode_NullPointer); - } - - ServerContext& context = OrthancRestApi::GetContext(call); - - bool permissive = Toolbox::GetJsonBooleanField(request, "Permissive", false); - bool asynchronous = Toolbox::GetJsonBooleanField(request, "Asynchronous", false); - int priority = Toolbox::GetJsonIntegerField(request, "Priority", 0); - - job->SetPermissive(permissive); - - Json::Value publicContent; - - if (asynchronous) - { - // Asynchronous mode: Submit the job, but don't wait for its completion - std::string id; - context.GetJobsEngine().GetRegistry().Submit(id, job.release(), priority); - - Json::Value v; - v["ID"] = id; - call.GetOutput().AnswerJson(v); - } - else if (context.GetJobsEngine().GetRegistry().SubmitAndWait - (publicContent, job.release(), priority)) - { - // Synchronous mode: We have submitted and waited for completion - call.GetOutput().AnswerBuffer("{}", "application/json"); - } - else - { - call.GetOutput().SignalError(HttpStatus_500_InternalServerError); - } - } - - static void DicomStore(RestApiPostCall& call) { ServerContext& context = OrthancRestApi::GetContext(call); @@ -783,18 +739,16 @@ int moveOriginatorID = Toolbox::GetJsonIntegerField (request, "MoveOriginatorID", 0 /* By default, not a C-MOVE */); - RemoteModalityParameters p = Configuration::GetModalityUsingSymbolicName(remote); - - job->SetDescription("REST API"); job->SetLocalAet(localAet); - job->SetRemoteModality(p); + job->SetRemoteModality(Configuration::GetModalityUsingSymbolicName(remote)); if (moveOriginatorID != 0) { job->SetMoveOriginator(moveOriginatorAET, moveOriginatorID); } - SubmitJob(call, request, job.release()); + OrthancRestApi::GetApi(call).SubmitCommandsJob + (call, job.release(), true /* synchronous by default */, request); } } @@ -925,9 +879,9 @@ WebServiceParameters peer; if (Configuration::GetOrthancPeer(peer, remote)) { - job->SetDescription("REST API"); job->SetPeer(peer); - SubmitJob(call, request, job.release()); + OrthancRestApi::GetApi(call).SubmitCommandsJob + (call, job.release(), true /* synchronous by default */, request); } else { diff -r 251614c2edac -r abce036683cd OrthancServer/ServerJobs/ResourceModificationJob.cpp --- a/OrthancServer/ServerJobs/ResourceModificationJob.cpp Mon Oct 08 16:08:51 2018 +0200 +++ b/OrthancServer/ServerJobs/ResourceModificationJob.cpp Mon Oct 08 17:05:19 2018 +0200 @@ -39,88 +39,100 @@ namespace Orthanc { - ResourceModificationJob::Output::Output(ResourceType level) : - level_(level), - isFirst_(true) + class ResourceModificationJob::Output : public boost::noncopyable { - if (level_ != ResourceType_Patient && - level_ != ResourceType_Study && - level_ != ResourceType_Series) + private: + 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); + } + } + + ResourceType GetLevel() const { - throw OrthancException(ErrorCode_ParameterOutOfRange); - } - } + return level_; + } + + + void Update(DicomInstanceHasher& hasher) + { + 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); + } + + patientId_ = hasher.HashPatient(); + isFirst_ = false; + } + } - void ResourceModificationJob::Output::Update(DicomInstanceHasher& hasher) - { - boost::mutex::scoped_lock lock(mutex_); - - if (isFirst_) + bool Format(Json::Value& target) { - switch (level_) + if (isFirst_) { - 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); + return false; } - - patientId_ = hasher.HashPatient(); - isFirst_ = false; + else + { + target = Json::objectValue; + target["Type"] = EnumerationToString(level_); + target["ID"] = id_; + target["Path"] = GetBasePath(level_, id_); + target["PatientID"] = patientId_; + return true; + } } - } - - - bool ResourceModificationJob::Output::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; - } - } - bool ResourceModificationJob::Output::GetIdentifier(std::string& id) - { - boost::mutex::scoped_lock lock(mutex_); - - if (isFirst_) + bool GetIdentifier(std::string& id) { - return false; + if (isFirst_) + { + return false; + } + else + { + id = id_; + return true; + } } - else - { - id = id_; - return true; - } - } + }; + + bool ResourceModificationJob::HandleInstance(const std::string& instance) { - if (modification_.get() == NULL) + if (modification_.get() == NULL || + output_.get() == NULL) { LOG(ERROR) << "No modification was provided for this job"; throw OrthancException(ErrorCode_BadSequenceOfCalls); @@ -204,14 +216,9 @@ throw OrthancException(ErrorCode_CannotStoreInstance); } - // Sanity checks in debug mode assert(modifiedInstance == modifiedHasher.HashInstance()); - - if (output_.get() != NULL) - { - output_->Update(modifiedHasher); - } + output_->Update(modifiedHasher); return true; } @@ -224,6 +231,7 @@ void ResourceModificationJob::SetModification(DicomModification* modification, + ResourceType level, bool isAnonymization) { if (modification == NULL) @@ -237,24 +245,12 @@ else { modification_.reset(modification); + output_.reset(new Output(level)); isAnonymization_ = isAnonymization; } } - void ResourceModificationJob::SetOutput(boost::shared_ptr& output) - { - if (IsStarted()) - { - throw OrthancException(ErrorCode_BadSequenceOfCalls); - } - else - { - output_ = output; - } - } - - void ResourceModificationJob::SetOrigin(const DicomInstanceOrigin& origin) { if (IsStarted()) @@ -292,6 +288,11 @@ SetOfInstancesJob::GetPublicContent(value); value["IsAnonymization"] = isAnonymization_; + + if (output_.get() != NULL) + { + output_->Format(value); + } } diff -r 251614c2edac -r abce036683cd OrthancServer/ServerJobs/ResourceModificationJob.h --- a/OrthancServer/ServerJobs/ResourceModificationJob.h Mon Oct 08 16:08:51 2018 +0200 +++ b/OrthancServer/ServerJobs/ResourceModificationJob.h Mon Oct 08 17:05:19 2018 +0200 @@ -40,32 +40,9 @@ { class ResourceModificationJob : public SetOfInstancesJob { - public: - class Output : public boost::noncopyable - { - private: - boost::mutex mutex_; - ResourceType level_; - bool isFirst_; - std::string id_; - std::string patientId_; - - public: - Output(ResourceType level); - - ResourceType GetLevel() const - { - return level_; - } - - void Update(DicomInstanceHasher& hasher); - - bool Format(Json::Value& target); - - bool GetIdentifier(std::string& id); - }; + private: + class Output; - private: ServerContext& context_; std::auto_ptr modification_; boost::shared_ptr output_; @@ -88,10 +65,9 @@ const Json::Value& serialized); void SetModification(DicomModification* modification, // Takes ownership + ResourceType level, bool isAnonymization); - void SetOutput(boost::shared_ptr& output); - void SetOrigin(const DicomInstanceOrigin& origin); void SetOrigin(const RestApiCall& call); diff -r 251614c2edac -r abce036683cd UnitTestsSources/MultiThreadingTests.cpp --- a/UnitTestsSources/MultiThreadingTests.cpp Mon Oct 08 16:08:51 2018 +0200 +++ b/UnitTestsSources/MultiThreadingTests.cpp Mon Oct 08 17:05:19 2018 +0200 @@ -1548,7 +1548,7 @@ modification->SetupAnonymization(DicomVersion_2008); ResourceModificationJob job(GetContext()); - job.SetModification(modification.release(), true); + job.SetModification(modification.release(), ResourceType_Patient, true); job.SetOrigin(DicomInstanceOrigin::FromLua()); ASSERT_TRUE(CheckIdempotentSetOfInstances(unserializer, job));