Mercurial > hg > orthanc
comparison OrthancServer/OrthancRestApi.cpp @ 306:326d5a4a5af3
modification of instances
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Thu, 20 Dec 2012 16:44:50 +0100 |
parents | 86bb79522f19 |
children | 485db3b07740 |
comparison
equal
deleted
inserted
replaced
305:86bb79522f19 | 306:326d5a4a5af3 |
---|---|
840 | 840 |
841 | 841 |
842 // Modification of DICOM instances ------------------------------------------ | 842 // Modification of DICOM instances ------------------------------------------ |
843 | 843 |
844 static void ReplaceInstanceInternal(ParsedDicomFile& toModify, | 844 static void ReplaceInstanceInternal(ParsedDicomFile& toModify, |
845 const Json::Value& removals, | |
845 const Json::Value& replacements, | 846 const Json::Value& replacements, |
846 DicomReplaceMode mode) | 847 DicomReplaceMode mode) |
847 { | 848 { |
848 if (!replacements.isObject()) | 849 if (!replacements.isObject() || |
850 !removals.isArray()) | |
849 { | 851 { |
850 throw OrthancException(ErrorCode_BadRequest); | 852 throw OrthancException(ErrorCode_BadRequest); |
851 } | 853 } |
852 | 854 |
855 for (Json::Value::ArrayIndex i = 0; i < removals.size(); i++) | |
856 { | |
857 DicomTag tag = FromDcmtkBridge::ParseTag(removals[i].asString()); | |
858 toModify.Remove(tag); | |
859 } | |
860 | |
853 Json::Value::Members members = replacements.getMemberNames(); | 861 Json::Value::Members members = replacements.getMemberNames(); |
854 | |
855 for (size_t i = 0; i < members.size(); i++) | 862 for (size_t i = 0; i < members.size(); i++) |
856 { | 863 { |
857 const std::string& name = members[i]; | 864 const std::string& name = members[i]; |
858 std::string value = replacements[name].asString(); | 865 std::string value = replacements[name].asString(); |
859 | 866 |
864 // A new SOP instance UID is automatically generated | 871 // A new SOP instance UID is automatically generated |
865 std::string instanceUid = FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Instance); | 872 std::string instanceUid = FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Instance); |
866 toModify.Replace(DICOM_TAG_SOP_INSTANCE_UID, instanceUid, DicomReplaceMode_InsertIfAbsent); | 873 toModify.Replace(DICOM_TAG_SOP_INSTANCE_UID, instanceUid, DicomReplaceMode_InsertIfAbsent); |
867 } | 874 } |
868 | 875 |
869 | 876 |
870 | 877 static bool ParseModifyRequest(Json::Value& removals, |
878 Json::Value& replacements, | |
879 const RestApi::PostCall& call) | |
880 { | |
881 Json::Value request; | |
882 if (call.ParseJsonRequest(request) && | |
883 request.isObject()) | |
884 { | |
885 removals = Json::arrayValue; | |
886 replacements = Json::objectValue; | |
887 | |
888 if (request.isMember("Remove")) | |
889 { | |
890 removals = request["Remove"]; | |
891 } | |
892 | |
893 if (request.isMember("Replace")) | |
894 { | |
895 replacements = request["Replace"]; | |
896 } | |
897 | |
898 return true; | |
899 } | |
900 else | |
901 { | |
902 return false; | |
903 } | |
904 } | |
871 | 905 |
872 | 906 |
873 static void ModifyInstance(RestApi::PostCall& call) | 907 static void ModifyInstance(RestApi::PostCall& call) |
874 { | 908 { |
875 RETRIEVE_CONTEXT(call); | 909 RETRIEVE_CONTEXT(call); |
876 | 910 |
877 std::string id = call.GetUriComponent("id", ""); | 911 std::string id = call.GetUriComponent("id", ""); |
878 ParsedDicomFile& dicom = context.GetDicomFile(id); | 912 ParsedDicomFile& dicom = context.GetDicomFile(id); |
879 | 913 |
880 Json::Value request; | 914 Json::Value removals, replacements; |
881 if (call.ParseJsonRequest(request)) | 915 if (ParseModifyRequest(removals, replacements, call)) |
882 { | 916 { |
883 std::auto_ptr<ParsedDicomFile> modified(dicom.Clone()); | 917 std::auto_ptr<ParsedDicomFile> modified(dicom.Clone()); |
884 ReplaceInstanceInternal(*modified, request, DicomReplaceMode_InsertIfAbsent); | 918 ReplaceInstanceInternal(*modified, removals, replacements, DicomReplaceMode_InsertIfAbsent); |
919 context.GetIndex().SetMetadata(id, MetadataType_ModifiedFrom, id); | |
885 modified->Answer(call.GetOutput()); | 920 modified->Answer(call.GetOutput()); |
886 } | 921 } |
887 | 922 } |
888 /*std::string studyUid = FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Study); | 923 |
889 std::string seriesUid = FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Series); | 924 |
890 modified->Replace(DICOM_TAG_SERIES_INSTANCE_UID, seriesUid); | 925 template <enum ResourceType resourceType> |
891 modified->Replace(DICOM_TAG_STUDY_INSTANCE_UID, studyUid);*/ | 926 static void ModifyInplace(RestApi::PostCall& call) |
927 { | |
928 typedef std::list<std::string> Instances; | |
929 | |
930 RETRIEVE_CONTEXT(call); | |
931 | |
932 Instances instances; | |
933 std::string id = call.GetUriComponent("id", ""); | |
934 context.GetIndex().GetChildInstances(instances, id); | |
935 | |
936 if (instances.size() == 0) | |
937 { | |
938 return; | |
939 } | |
940 | |
941 Json::Value removals, replacements; | |
942 if (ParseModifyRequest(removals, replacements, call)) | |
943 { | |
944 switch (resourceType) | |
945 { | |
946 // DO NOT ADD "break" OR CHANGE THE ORDER BELOW | |
947 case ResourceType_Patient: | |
948 replacements["0010-0020"] = FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Patient); | |
949 | |
950 case ResourceType_Study: | |
951 replacements["0020-000d"] = FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Study); | |
952 | |
953 case ResourceType_Series: | |
954 replacements["0020-000e"] = FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Series); | |
955 break; | |
956 | |
957 default: | |
958 throw OrthancException(ErrorCode_InternalError); | |
959 } | |
960 | |
961 std::string modifiedId; | |
962 for (Instances::const_iterator it = instances.begin(); | |
963 it != instances.end(); it++) | |
964 { | |
965 LOG(INFO) << "Modifying instance " << *it; | |
966 ParsedDicomFile& dicom = context.GetDicomFile(*it); | |
967 std::auto_ptr<ParsedDicomFile> modified(dicom.Clone()); | |
968 ReplaceInstanceInternal(*modified, removals, replacements, DicomReplaceMode_InsertIfAbsent); | |
969 | |
970 if (context.Store(modifiedId, modified->GetDicom()) != StoreStatus_Success) | |
971 { | |
972 LOG(ERROR) << "Error while modifying the instance " << *it; | |
973 return; | |
974 } | |
975 | |
976 context.GetIndex().SetMetadata(modifiedId, MetadataType_ModifiedFrom, *it); | |
977 } | |
978 | |
979 | |
980 int level; | |
981 std::string id; | |
982 switch (resourceType) | |
983 { | |
984 case ResourceType_Series: level = 1; break; | |
985 case ResourceType_Study: level = 2; break; | |
986 case ResourceType_Patient: level = 3; break; | |
987 default: | |
988 throw OrthancException(ErrorCode_InternalError); | |
989 } | |
990 | |
991 for (int i = 0; i < level; i++) | |
992 { | |
993 if (!context.GetIndex().LookupParent(id, modifiedId)) | |
994 { | |
995 throw OrthancException(ErrorCode_InternalError); | |
996 } | |
997 | |
998 modifiedId = id; | |
999 } | |
1000 | |
1001 Json::Value result = Json::objectValue; | |
1002 result["ID"] = id; | |
1003 result["Path"] = GetBasePath(resourceType, id); | |
1004 call.GetOutput().AnswerJson(result); | |
1005 } | |
892 } | 1006 } |
893 | 1007 |
894 | 1008 |
895 | 1009 |
896 // Registration of the various REST handlers -------------------------------- | 1010 // Registration of the various REST handlers -------------------------------- |
947 Register("/modalities/{id}/find-series", DicomFindSeries); | 1061 Register("/modalities/{id}/find-series", DicomFindSeries); |
948 Register("/modalities/{id}/find", DicomFind); | 1062 Register("/modalities/{id}/find", DicomFind); |
949 Register("/modalities/{id}/store", DicomStore); | 1063 Register("/modalities/{id}/store", DicomStore); |
950 | 1064 |
951 Register("/instances/{id}/modify", ModifyInstance); | 1065 Register("/instances/{id}/modify", ModifyInstance); |
1066 Register("/series/{id}/modify", ModifyInplace<ResourceType_Series>); | |
1067 Register("/studies/{id}/modify", ModifyInplace<ResourceType_Study>); | |
1068 Register("/patients/{id}/modify", ModifyInplace<ResourceType_Patient>); | |
952 } | 1069 } |
953 } | 1070 } |