comparison OrthancFramework/Sources/DicomParsing/DicomModification.cpp @ 4687:fcd2dc7c8f31

"Replace", "Keep" and "Remove" in "/modify" and "/anonymize" accept paths to subsequences
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 09 Jun 2021 17:24:44 +0200
parents 693f049729ba
children 177ad026d219
comparison
equal deleted inserted replaced
4685:693f049729ba 4687:fcd2dc7c8f31
1074 throw OrthancException(ErrorCode_BadRequest); 1074 throw OrthancException(ErrorCode_BadRequest);
1075 } 1075 }
1076 1076
1077 std::string name = query[i].asString(); 1077 std::string name = query[i].asString();
1078 1078
1079 DicomTag tag = FromDcmtkBridge::ParseTag(name); 1079 const DicomPath path(DicomPath::Parse(name));
1080 1080
1081 if (!force && IsDatabaseKey(tag)) 1081 if (path.GetPrefixLength() == 0 &&
1082 !force &&
1083 IsDatabaseKey(path.GetFinalTag()))
1082 { 1084 {
1083 throw OrthancException(ErrorCode_BadRequest, 1085 throw OrthancException(ErrorCode_BadRequest,
1084 "Marking tag \"" + name + "\" as to be " + 1086 "Marking tag \"" + name + "\" as to be " +
1085 (operation == DicomModification::TagOperation_Keep ? "kept" : "removed") + 1087 (operation == DicomModification::TagOperation_Keep ? "kept" : "removed") +
1086 " requires the \"Force\" option to be set to true"); 1088 " requires the \"Force\" option to be set to true");
1087 } 1089 }
1088 1090
1089 switch (operation) 1091 switch (operation)
1090 { 1092 {
1091 case DicomModification::TagOperation_Keep: 1093 case DicomModification::TagOperation_Keep:
1092 target.Keep(tag); 1094 target.Keep(path);
1093 LOG(TRACE) << "Keep: " << name << " (" << tag.Format() << ")"; 1095 LOG(TRACE) << "Keep: " << name << " = " << path.Format();
1094 break; 1096 break;
1095 1097
1096 case DicomModification::TagOperation_Remove: 1098 case DicomModification::TagOperation_Remove:
1097 target.Remove(tag); 1099 target.Remove(path);
1098 LOG(TRACE) << "Remove: " << name << " (" << tag.Format() << ")"; 1100 LOG(TRACE) << "Remove: " << name << " = " << path.Format();
1099 break; 1101 break;
1100 1102
1101 default: 1103 default:
1102 throw OrthancException(ErrorCode_InternalError); 1104 throw OrthancException(ErrorCode_InternalError);
1103 } 1105 }
1118 for (size_t i = 0; i < members.size(); i++) 1120 for (size_t i = 0; i < members.size(); i++)
1119 { 1121 {
1120 const std::string& name = members[i]; 1122 const std::string& name = members[i];
1121 const Json::Value& value = replacements[name]; 1123 const Json::Value& value = replacements[name];
1122 1124
1123 DicomTag tag = FromDcmtkBridge::ParseTag(name); 1125 const DicomPath path(DicomPath::Parse(name));
1124 1126
1125 if (!force && IsDatabaseKey(tag)) 1127 if (path.GetPrefixLength() == 0 &&
1128 !force &&
1129 IsDatabaseKey(path.GetFinalTag()))
1126 { 1130 {
1127 throw OrthancException(ErrorCode_BadRequest, 1131 throw OrthancException(ErrorCode_BadRequest,
1128 "Marking tag \"" + name + "\" as to be replaced " + 1132 "Marking tag \"" + name + "\" as to be replaced " +
1129 "requires the \"Force\" option to be set to true"); 1133 "requires the \"Force\" option to be set to true");
1130 } 1134 }
1131 1135
1132 target.Replace(tag, value, false /* not safe for anonymization */); 1136 target.Replace(path, value, false /* not safe for anonymization */);
1133 1137
1134 LOG(TRACE) << "Replace: " << name << " (" << tag.Format() 1138 LOG(TRACE) << "Replace: " << name << " = " << path.Format()
1135 << ") == " << value.toStyledString(); 1139 << " by: " << value.toStyledString();
1136 } 1140 }
1137 } 1141 }
1138 1142
1139 1143
1140 static bool GetBooleanValue(const std::string& member, 1144 static bool GetBooleanValue(const std::string& member,
1280 static const char* REPLACEMENTS = "Replacements"; 1284 static const char* REPLACEMENTS = "Replacements";
1281 static const char* MAP_PATIENTS = "MapPatients"; 1285 static const char* MAP_PATIENTS = "MapPatients";
1282 static const char* MAP_STUDIES = "MapStudies"; 1286 static const char* MAP_STUDIES = "MapStudies";
1283 static const char* MAP_SERIES = "MapSeries"; 1287 static const char* MAP_SERIES = "MapSeries";
1284 static const char* MAP_INSTANCES = "MapInstances"; 1288 static const char* MAP_INSTANCES = "MapInstances";
1285 static const char* PRIVATE_CREATOR = "PrivateCreator"; // New in Orthanc 1.6.0 1289 static const char* PRIVATE_CREATOR = "PrivateCreator"; // New in Orthanc 1.6.0
1286 static const char* UIDS = "Uids"; // New in Orthanc 1.9.4 1290 static const char* UIDS = "Uids"; // New in Orthanc 1.9.4
1287 static const char* REMOVED_RANGES = "RemovedRanges"; // New in Orthanc 1.9.4 1291 static const char* REMOVED_RANGES = "RemovedRanges"; // New in Orthanc 1.9.4
1292 static const char* KEEP_SEQUENCES = "KeepSequences"; // New in Orthanc 1.9.4
1293 static const char* REMOVE_SEQUENCES = "RemoveSequences"; // New in Orthanc 1.9.4
1294 static const char* SEQUENCE_REPLACEMENTS = "SequenceReplacements"; // New in Orthanc 1.9.4
1288 1295
1289 void DicomModification::Serialize(Json::Value& value) const 1296 void DicomModification::Serialize(Json::Value& value) const
1290 { 1297 {
1291 if (identifierGenerator_ != NULL) 1298 if (identifierGenerator_ != NULL)
1292 { 1299 {
1375 item.append(it->GetElementTo()); 1382 item.append(it->GetElementTo());
1376 ranges.append(item); 1383 ranges.append(item);
1377 } 1384 }
1378 1385
1379 value[REMOVED_RANGES] = ranges; 1386 value[REMOVED_RANGES] = ranges;
1387
1388 // New in Orthanc 1.9.4
1389 Json::Value lst = Json::arrayValue;
1390 for (ListOfPaths::const_iterator it = keepSequences_.begin(); it != keepSequences_.end(); ++it)
1391 {
1392 assert(it->GetPrefixLength() > 0);
1393 lst.append(it->Format());
1394 }
1395
1396 value[KEEP_SEQUENCES] = lst;
1397
1398 // New in Orthanc 1.9.4
1399 lst = Json::arrayValue;
1400 for (ListOfPaths::const_iterator it = removeSequences_.begin(); it != removeSequences_.end(); ++it)
1401 {
1402 assert(it->GetPrefixLength() > 0);
1403 lst.append(it->Format());
1404 }
1405
1406 value[REMOVE_SEQUENCES] = lst;
1407
1408 // New in Orthanc 1.9.4
1409 lst = Json::objectValue;
1410 for (SequenceReplacements::const_iterator it = sequenceReplacements_.begin(); it != sequenceReplacements_.end(); ++it)
1411 {
1412 assert(*it != NULL);
1413 assert((*it)->GetPath().GetPrefixLength() > 0);
1414 lst[(*it)->GetPath().Format()] = (*it)->GetValue();
1415 }
1416
1417 value[SEQUENCE_REPLACEMENTS] = lst;
1380 } 1418 }
1381 1419
1382 void DicomModification::UnserializeUidMap(ResourceType level, 1420 void DicomModification::UnserializeUidMap(ResourceType level,
1383 const Json::Value& serialized, 1421 const Json::Value& serialized,
1384 const char* field) 1422 const char* field)
1509 } 1547 }
1510 } 1548 }
1511 } 1549 }
1512 } 1550 }
1513 } 1551 }
1552
1553 // New in Orthanc 1.9.4
1554 if (serialized.isMember(KEEP_SEQUENCES))
1555 {
1556 const Json::Value& keep = serialized[KEEP_SEQUENCES];
1557
1558 if (keep.type() != Json::arrayValue)
1559 {
1560 throw OrthancException(ErrorCode_BadFileFormat);
1561 }
1562 else
1563 {
1564 for (Json::Value::ArrayIndex i = 0; i < keep.size(); i++)
1565 {
1566 if (keep[i].type() != Json::stringValue)
1567 {
1568 throw OrthancException(ErrorCode_BadFileFormat);
1569 }
1570 else
1571 {
1572 keepSequences_.push_back(DicomPath::Parse(keep[i].asString()));
1573 }
1574 }
1575 }
1576 }
1577
1578 // New in Orthanc 1.9.4
1579 if (serialized.isMember(REMOVE_SEQUENCES))
1580 {
1581 const Json::Value& remove = serialized[REMOVE_SEQUENCES];
1582
1583 if (remove.type() != Json::arrayValue)
1584 {
1585 throw OrthancException(ErrorCode_BadFileFormat);
1586 }
1587 else
1588 {
1589 for (Json::Value::ArrayIndex i = 0; i < remove.size(); i++)
1590 {
1591 if (remove[i].type() != Json::stringValue)
1592 {
1593 throw OrthancException(ErrorCode_BadFileFormat);
1594 }
1595 else
1596 {
1597 removeSequences_.push_back(DicomPath::Parse(remove[i].asString()));
1598 }
1599 }
1600 }
1601 }
1602
1603 // New in Orthanc 1.9.4
1604 if (serialized.isMember(SEQUENCE_REPLACEMENTS))
1605 {
1606 const Json::Value& replace = serialized[SEQUENCE_REPLACEMENTS];
1607
1608 if (replace.type() != Json::objectValue)
1609 {
1610 throw OrthancException(ErrorCode_BadFileFormat);
1611 }
1612 else
1613 {
1614 Json::Value::Members members = replace.getMemberNames();
1615 for (size_t i = 0; i < members.size(); i++)
1616 {
1617 sequenceReplacements_.push_back(
1618 new SequenceReplacement(DicomPath::Parse(members[i]), replace[members[i]]));
1619 }
1620 }
1621 }
1514 } 1622 }
1515 1623
1516 1624
1517 void DicomModification::SetPrivateCreator(const std::string &privateCreator) 1625 void DicomModification::SetPrivateCreator(const std::string &privateCreator)
1518 { 1626 {