# HG changeset patch # User Sebastien Jodogne # Date 1356085107 -3600 # Node ID 6ab6cdeedf4ecd0726ad347bb249af070f7db05b # Parent ee97f0923dddd7f915c3d2c3df6b140c56b818d7 global sequences diff -r ee97f0923ddd -r 6ab6cdeedf4e OrthancServer/DatabaseWrapper.cpp --- a/OrthancServer/DatabaseWrapper.cpp Fri Dec 21 10:49:15 2012 +0100 +++ b/OrthancServer/DatabaseWrapper.cpp Fri Dec 21 11:18:27 2012 +0100 @@ -866,4 +866,32 @@ // Nothing to do: The patient is already unprotected } } + + + uint64_t DatabaseWrapper::IncrementGlobalSequence(GlobalProperty property) + { + std::string oldValue; + + if (LookupGlobalProperty(oldValue, property)) + { + uint64_t oldNumber; + + try + { + oldNumber = boost::lexical_cast(oldValue); + SetGlobalProperty(property, boost::lexical_cast(oldNumber + 1)); + return oldNumber + 1; + } + catch (boost::bad_lexical_cast&) + { + throw OrthancException(ErrorCode_InternalError); + } + } + else + { + // Initialize the sequence at "1" + SetGlobalProperty(property, "1"); + return 1; + } + } } diff -r ee97f0923ddd -r 6ab6cdeedf4e OrthancServer/DatabaseWrapper.h --- a/OrthancServer/DatabaseWrapper.h Fri Dec 21 10:49:15 2012 +0100 +++ b/OrthancServer/DatabaseWrapper.h Fri Dec 21 11:18:27 2012 +0100 @@ -210,5 +210,7 @@ { db_.FlushToDisk(); } + + uint64_t IncrementGlobalSequence(GlobalProperty property); }; } diff -r ee97f0923ddd -r 6ab6cdeedf4e OrthancServer/OrthancRestApi.cpp --- a/OrthancServer/OrthancRestApi.cpp Fri Dec 21 10:49:15 2012 +0100 +++ b/OrthancServer/OrthancRestApi.cpp Fri Dec 21 11:18:27 2012 +0100 @@ -841,22 +841,59 @@ // Modification of DICOM instances ------------------------------------------ + typedef std::set Removals; + typedef std::map Replacements; + static void ReplaceInstanceInternal(ParsedDicomFile& toModify, - const Json::Value& removals, - const Json::Value& replacements, + const Removals& removals, + const Replacements& replacements, DicomReplaceMode mode) { - if (!replacements.isObject() || - !removals.isArray()) + for (Removals::const_iterator it = removals.begin(); + it != removals.end(); it++) + { + toModify.Remove(*it); + } + + for (Replacements::const_iterator it = replacements.begin(); + it != replacements.end(); it++) + { + toModify.Replace(it->first, it->second, mode); + } + + // A new SOP instance UID is automatically generated + std::string instanceUid = FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Instance); + toModify.Replace(DICOM_TAG_SOP_INSTANCE_UID, instanceUid, DicomReplaceMode_InsertIfAbsent); + } + + + static void ParseRemovals(Removals& target, + const Json::Value& removals) + { + if (!removals.isArray()) { throw OrthancException(ErrorCode_BadRequest); } + target.clear(); + for (Json::Value::ArrayIndex i = 0; i < removals.size(); i++) { DicomTag tag = FromDcmtkBridge::ParseTag(removals[i].asString()); - toModify.Remove(tag); + target.insert(tag); } + } + + + static void ParseReplacements(Replacements& target, + const Json::Value& replacements) + { + if (!replacements.isObject()) + { + throw OrthancException(ErrorCode_BadRequest); + } + + target.clear(); Json::Value::Members members = replacements.getMemberNames(); for (size_t i = 0; i < members.size(); i++) @@ -865,36 +902,67 @@ std::string value = replacements[name].asString(); DicomTag tag = FromDcmtkBridge::ParseTag(name); - toModify.Replace(tag, value, mode); + target[tag] = value; } - - // A new SOP instance UID is automatically generated - std::string instanceUid = FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Instance); - toModify.Replace(DICOM_TAG_SOP_INSTANCE_UID, instanceUid, DicomReplaceMode_InsertIfAbsent); } - - static bool ParseModifyRequest(Json::Value& removals, - Json::Value& replacements, + + static void SetupAnonymization(Removals& removals, + Replacements& replacements) + { + removals.clear(); + replacements.clear(); + + // This is table X.1-1 from DICOM supplement 55: Attribute Level Confidentiality + removals.insert(DicomTag(0x0008, 0x0014)); // Instance Creator UID + // 0008-0018 - SOP Instance UID is automatically set by ReplaceInstanceInternal() + removals.insert(DicomTag(0x0008, 0x0050)); // Accession number +/* removals.insert(DicomTag(0x0008, 0x )); // + removals.insert(DicomTag(0x , 0x )); // + removals.insert(DicomTag(0x , 0x )); // + removals.insert(DicomTag(0x , 0x )); // + removals.insert(DicomTag(0x , 0x )); // + removals.insert(DicomTag(0x , 0x )); // + removals.insert(DicomTag(0x , 0x )); // + removals.insert(DicomTag(0x , 0x )); // + removals.insert(DicomTag(0x , 0x )); // + removals.insert(DicomTag(0x , 0x )); // + removals.insert(DicomTag(0x , 0x )); // + removals.insert(DicomTag(0x , 0x )); // + removals.insert(DicomTag(0x , 0x )); // + removals.insert(DicomTag(0x , 0x )); // + removals.insert(DicomTag(0x , 0x )); // + removals.insert(DicomTag(0x , 0x )); // + removals.insert(DicomTag(0x , 0x )); // + removals.insert(DicomTag(0x , 0x )); // +*/ + } + + + static bool ParseModifyRequest(Removals& removals, + Replacements& replacements, const RestApi::PostCall& call) { Json::Value request; if (call.ParseJsonRequest(request) && request.isObject()) { - removals = Json::arrayValue; - replacements = Json::objectValue; + Json::Value removalsPart = Json::arrayValue; + Json::Value replacementsPart = Json::objectValue; if (request.isMember("Remove")) { - removals = request["Remove"]; + removalsPart = request["Remove"]; } if (request.isMember("Replace")) { - replacements = request["Replace"]; + replacementsPart = request["Replace"]; } + ParseRemovals(removals, removalsPart); + ParseReplacements(replacements, replacementsPart); + return true; } else @@ -911,7 +979,9 @@ std::string id = call.GetUriComponent("id", ""); ParsedDicomFile& dicom = context.GetDicomFile(id); - Json::Value removals, replacements; + Removals removals; + Replacements replacements; + if (ParseModifyRequest(removals, replacements, call)) { std::auto_ptr modified(dicom.Clone()); @@ -936,11 +1006,13 @@ return; } - Json::Value removals, replacements; + Removals removals; + Replacements replacements; + if (ParseModifyRequest(removals, replacements, call)) { std::string newSeriesId; - replacements["0020-000e"] = FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Series); + replacements[DICOM_TAG_SERIES_INSTANCE_UID] = FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Series); for (Instances::const_iterator it = instances.begin(); it != instances.end(); it++) @@ -990,12 +1062,13 @@ } SeriesUidMap seriesUidMap; + Removals removals; + Replacements replacements; - Json::Value removals, replacements; if (ParseModifyRequest(removals, replacements, call)) { std::string newStudyId; - replacements["0020-000d"] = FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Study); + replacements[DICOM_TAG_STUDY_INSTANCE_UID] = FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Study); for (Instances::const_iterator it = instances.begin(); it != instances.end(); it++) @@ -1014,11 +1087,11 @@ { std::string newSeriesUid = FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Series); seriesUidMap[seriesId] = newSeriesUid; - replacements["0020-000e"] = newSeriesUid; + replacements[DICOM_TAG_SERIES_INSTANCE_UID] = newSeriesUid; } else { - replacements["0020-000e"] = it2->second; + replacements[DICOM_TAG_SERIES_INSTANCE_UID] = it2->second; } std::auto_ptr modified(dicom.Clone()); diff -r ee97f0923ddd -r 6ab6cdeedf4e OrthancServer/ServerEnumerations.h --- a/OrthancServer/ServerEnumerations.h Fri Dec 21 10:49:15 2012 +0100 +++ b/OrthancServer/ServerEnumerations.h Fri Dec 21 11:18:27 2012 +0100 @@ -60,7 +60,8 @@ enum GlobalProperty { GlobalProperty_DatabaseSchemaVersion = 1, - GlobalProperty_FlushSleep = 2 + GlobalProperty_FlushSleep = 2, + GlobalProperty_AnonymizationSequence = 3 }; enum ResourceType diff -r ee97f0923ddd -r 6ab6cdeedf4e OrthancServer/ServerIndex.cpp --- a/OrthancServer/ServerIndex.cpp Fri Dec 21 10:49:15 2012 +0100 +++ b/OrthancServer/ServerIndex.cpp Fri Dec 21 11:18:27 2012 +0100 @@ -1069,4 +1069,11 @@ return false; } } + + + uint64_t ServerIndex::IncrementGlobalSequence(GlobalProperty sequence) + { + boost::mutex::scoped_lock lock(mutex_); + return db_->IncrementGlobalSequence(sequence); + } } diff -r ee97f0923ddd -r 6ab6cdeedf4e OrthancServer/ServerIndex.h --- a/OrthancServer/ServerIndex.h Fri Dec 21 10:49:15 2012 +0100 +++ b/OrthancServer/ServerIndex.h Fri Dec 21 11:18:27 2012 +0100 @@ -156,5 +156,7 @@ bool LookupParent(std::string& target, const std::string& publicId); + + uint64_t IncrementGlobalSequence(GlobalProperty sequence); }; } diff -r ee97f0923ddd -r 6ab6cdeedf4e UnitTests/ServerIndex.cpp --- a/UnitTests/ServerIndex.cpp Fri Dec 21 10:49:15 2012 +0100 +++ b/UnitTests/ServerIndex.cpp Fri Dec 21 11:18:27 2012 +0100 @@ -404,3 +404,16 @@ ASSERT_EQ(0u, index.GetTableRecordCount("Resources")); ASSERT_EQ(0u, index.GetTableRecordCount("PatientRecyclingOrder")); } + + + +TEST(DatabaseWrapper, Sequence) +{ + ServerIndexListener listener; + DatabaseWrapper index(listener); + + ASSERT_EQ(1u, index.IncrementGlobalSequence(GlobalProperty_AnonymizationSequence)); + ASSERT_EQ(2u, index.IncrementGlobalSequence(GlobalProperty_AnonymizationSequence)); + ASSERT_EQ(3u, index.IncrementGlobalSequence(GlobalProperty_AnonymizationSequence)); + ASSERT_EQ(4u, index.IncrementGlobalSequence(GlobalProperty_AnonymizationSequence)); +}