comparison OrthancServer/Sources/ServerContext.cpp @ 5568:b0b5546f1b9f find-refactoring

find refactor: re-use existing code. /studies?expand is almost fully implemented with new code
author Alain Mazy <am@orthanc.team>
date Thu, 25 Apr 2024 09:22:07 +0200
parents acdb8d78bf99
children 77570cce8855
comparison
equal deleted inserted replaced
5567:f3562c1a150d 5568:b0b5546f1b9f
2123 2123
2124 2124
2125 static void SerializeExpandedResource(Json::Value& target, 2125 static void SerializeExpandedResource(Json::Value& target,
2126 const ExpandedResource& resource, 2126 const ExpandedResource& resource,
2127 DicomToJsonFormat format, 2127 DicomToJsonFormat format,
2128 const std::set<DicomTag>& requestedTags) 2128 const std::set<DicomTag>& requestedTags,
2129 ExpandResourceFlags expandFlags)
2129 { 2130 {
2130 target = Json::objectValue; 2131 target = Json::objectValue;
2131 2132
2132 target["Type"] = GetResourceTypeText(resource.GetLevel(), false, true); 2133 target["Type"] = GetResourceTypeText(resource.GetLevel(), false, true);
2133 target["ID"] = resource.GetPublicId(); 2134 target["ID"] = resource.GetPublicId();
2134 2135
2135 switch (resource.GetLevel()) 2136 if (!resource.parentId_.empty())
2136 { 2137 {
2137 case ResourceType_Patient: 2138 switch (resource.GetLevel())
2138 break; 2139 {
2139 2140 case ResourceType_Patient:
2140 case ResourceType_Study: 2141 break;
2141 target["ParentPatient"] = resource.parentId_; 2142
2142 break; 2143 case ResourceType_Study:
2143 2144 target["ParentPatient"] = resource.parentId_;
2144 case ResourceType_Series: 2145 break;
2145 target["ParentStudy"] = resource.parentId_; 2146
2146 break; 2147 case ResourceType_Series:
2147 2148 target["ParentStudy"] = resource.parentId_;
2148 case ResourceType_Instance: 2149 break;
2149 target["ParentSeries"] = resource.parentId_; 2150
2150 break; 2151 case ResourceType_Instance:
2151 2152 target["ParentSeries"] = resource.parentId_;
2152 default: 2153 break;
2153 throw OrthancException(ErrorCode_InternalError); 2154
2154 } 2155 default:
2155 2156 throw OrthancException(ErrorCode_InternalError);
2156 switch (resource.GetLevel()) 2157 }
2157 { 2158 }
2158 case ResourceType_Patient: 2159
2159 case ResourceType_Study: 2160 if ((expandFlags & ExpandResourceFlags_IncludeChildren) != 0)
2160 case ResourceType_Series: 2161 {
2161 { 2162 switch (resource.GetLevel())
2162 Json::Value c = Json::arrayValue; 2163 {
2163 2164 case ResourceType_Patient:
2164 for (std::list<std::string>::const_iterator 2165 case ResourceType_Study:
2165 it = resource.childrenIds_.begin(); it != resource.childrenIds_.end(); ++it) 2166 case ResourceType_Series:
2166 { 2167 {
2167 c.append(*it); 2168 Json::Value c = Json::arrayValue;
2168 } 2169
2169 2170 for (std::list<std::string>::const_iterator
2170 if (resource.GetLevel() == ResourceType_Patient) 2171 it = resource.childrenIds_.begin(); it != resource.childrenIds_.end(); ++it)
2171 { 2172 {
2172 target["Studies"] = c; 2173 c.append(*it);
2173 } 2174 }
2174 else if (resource.GetLevel() == ResourceType_Study) 2175
2175 { 2176 if (resource.GetLevel() == ResourceType_Patient)
2176 target["Series"] = c; 2177 {
2177 } 2178 target["Studies"] = c;
2178 else 2179 }
2179 { 2180 else if (resource.GetLevel() == ResourceType_Study)
2180 target["Instances"] = c; 2181 {
2181 } 2182 target["Series"] = c;
2182 break; 2183 }
2183 } 2184 else
2184 2185 {
2185 case ResourceType_Instance: 2186 target["Instances"] = c;
2186 break; 2187 }
2187 2188 break;
2188 default: 2189 }
2189 throw OrthancException(ErrorCode_InternalError); 2190
2190 } 2191 case ResourceType_Instance:
2191 2192 break;
2192 switch (resource.GetLevel()) 2193
2193 { 2194 default:
2194 case ResourceType_Patient: 2195 throw OrthancException(ErrorCode_InternalError);
2195 case ResourceType_Study: 2196 }
2196 break; 2197 }
2197 2198
2198 case ResourceType_Series: 2199 if ((expandFlags & ExpandResourceFlags_IncludeMetadata) != 0)
2199 if (resource.expectedNumberOfInstances_ < 0) 2200 {
2200 { 2201 switch (resource.GetLevel())
2201 target["ExpectedNumberOfInstances"] = Json::nullValue; 2202 {
2202 } 2203 case ResourceType_Patient:
2203 else 2204 case ResourceType_Study:
2204 { 2205 break;
2205 target["ExpectedNumberOfInstances"] = resource.expectedNumberOfInstances_; 2206
2206 } 2207 case ResourceType_Series:
2207 target["Status"] = resource.status_; 2208 if (resource.expectedNumberOfInstances_ < 0)
2208 break; 2209 {
2209 2210 target["ExpectedNumberOfInstances"] = Json::nullValue;
2210 case ResourceType_Instance: 2211 }
2211 { 2212 else
2212 target["FileSize"] = static_cast<unsigned int>(resource.fileSize_); 2213 {
2213 target["FileUuid"] = resource.fileUuid_; 2214 target["ExpectedNumberOfInstances"] = resource.expectedNumberOfInstances_;
2214 2215 }
2215 if (resource.indexInSeries_ < 0) 2216 target["Status"] = resource.status_;
2216 { 2217 break;
2217 target["IndexInSeries"] = Json::nullValue; 2218
2218 } 2219 case ResourceType_Instance:
2219 else 2220 {
2220 { 2221 target["FileSize"] = static_cast<unsigned int>(resource.fileSize_);
2221 target["IndexInSeries"] = resource.indexInSeries_; 2222 target["FileUuid"] = resource.fileUuid_;
2222 } 2223
2223 2224 if (resource.indexInSeries_ < 0)
2224 break; 2225 {
2225 } 2226 target["IndexInSeries"] = Json::nullValue;
2226 2227 }
2227 default: 2228 else
2228 throw OrthancException(ErrorCode_InternalError); 2229 {
2229 } 2230 target["IndexInSeries"] = resource.indexInSeries_;
2230 2231 }
2231 if (!resource.anonymizedFrom_.empty()) 2232
2232 { 2233 break;
2233 target["AnonymizedFrom"] = resource.anonymizedFrom_; 2234 }
2234 } 2235
2236 default:
2237 throw OrthancException(ErrorCode_InternalError);
2238 }
2235 2239
2236 if (!resource.modifiedFrom_.empty()) 2240 if (!resource.anonymizedFrom_.empty())
2237 { 2241 {
2238 target["ModifiedFrom"] = resource.modifiedFrom_; 2242 target["AnonymizedFrom"] = resource.anonymizedFrom_;
2243 }
2244
2245 if (!resource.modifiedFrom_.empty())
2246 {
2247 target["ModifiedFrom"] = resource.modifiedFrom_;
2248 }
2239 } 2249 }
2240 2250
2241 if (resource.GetLevel() == ResourceType_Patient || 2251 if (resource.GetLevel() == ResourceType_Patient ||
2242 resource.GetLevel() == ResourceType_Study || 2252 resource.GetLevel() == ResourceType_Study ||
2243 resource.GetLevel() == ResourceType_Series) 2253 resource.GetLevel() == ResourceType_Series)
2244 { 2254 {
2245 target["IsStable"] = resource.isStable_; 2255 if ((expandFlags & ExpandResourceFlags_IncludeIsStable) != 0)
2256 {
2257 target["IsStable"] = resource.isStable_;
2258 }
2246 2259
2247 if (!resource.lastUpdate_.empty()) 2260 if (!resource.lastUpdate_.empty())
2248 { 2261 {
2249 target["LastUpdate"] = resource.lastUpdate_; 2262 target["LastUpdate"] = resource.lastUpdate_;
2250 } 2263 }
2251 } 2264 }
2252 2265
2253 // serialize tags 2266 if ((expandFlags & ExpandResourceFlags_IncludeMainDicomTags) != 0)
2254 2267 {
2255 static const char* const MAIN_DICOM_TAGS = "MainDicomTags"; 2268 // serialize tags
2256 static const char* const PATIENT_MAIN_DICOM_TAGS = "PatientMainDicomTags"; 2269
2257 2270 static const char* const MAIN_DICOM_TAGS = "MainDicomTags";
2258 DicomMap mainDicomTags; 2271 static const char* const PATIENT_MAIN_DICOM_TAGS = "PatientMainDicomTags";
2259 resource.GetMainDicomTags().ExtractResourceInformation(mainDicomTags, resource.GetLevel()); 2272
2260 2273 DicomMap mainDicomTags;
2261 target[MAIN_DICOM_TAGS] = Json::objectValue; 2274 resource.GetMainDicomTags().ExtractResourceInformation(mainDicomTags, resource.GetLevel());
2262 FromDcmtkBridge::ToJson(target[MAIN_DICOM_TAGS], mainDicomTags, format); 2275
2263 2276 target[MAIN_DICOM_TAGS] = Json::objectValue;
2264 if (resource.GetLevel() == ResourceType_Study) 2277 FromDcmtkBridge::ToJson(target[MAIN_DICOM_TAGS], mainDicomTags, format);
2265 { 2278
2266 DicomMap patientMainDicomTags; 2279 if (resource.GetLevel() == ResourceType_Study)
2267 resource.GetMainDicomTags().ExtractPatientInformation(patientMainDicomTags); 2280 {
2268 2281 DicomMap patientMainDicomTags;
2269 target[PATIENT_MAIN_DICOM_TAGS] = Json::objectValue; 2282 resource.GetMainDicomTags().ExtractPatientInformation(patientMainDicomTags);
2270 FromDcmtkBridge::ToJson(target[PATIENT_MAIN_DICOM_TAGS], patientMainDicomTags, format); 2283
2271 } 2284 target[PATIENT_MAIN_DICOM_TAGS] = Json::objectValue;
2272 2285 FromDcmtkBridge::ToJson(target[PATIENT_MAIN_DICOM_TAGS], patientMainDicomTags, format);
2273 if (requestedTags.size() > 0) 2286 }
2274 { 2287
2275 static const char* const REQUESTED_TAGS = "RequestedTags"; 2288 if (requestedTags.size() > 0)
2276 2289 {
2277 DicomMap tags; 2290 static const char* const REQUESTED_TAGS = "RequestedTags";
2278 resource.GetMainDicomTags().ExtractTags(tags, requestedTags); 2291
2279 2292 DicomMap tags;
2280 target[REQUESTED_TAGS] = Json::objectValue; 2293 resource.GetMainDicomTags().ExtractTags(tags, requestedTags);
2281 FromDcmtkBridge::ToJson(target[REQUESTED_TAGS], tags, format); 2294
2282 2295 target[REQUESTED_TAGS] = Json::objectValue;
2283 } 2296 FromDcmtkBridge::ToJson(target[REQUESTED_TAGS], tags, format);
2284 2297
2298 }
2299 }
2300
2301 if ((expandFlags & ExpandResourceFlags_IncludeLabels) != 0)
2285 { 2302 {
2286 Json::Value labels = Json::arrayValue; 2303 Json::Value labels = Json::arrayValue;
2287 2304
2288 for (std::set<std::string>::const_iterator it = resource.labels_.begin(); it != resource.labels_.end(); ++it) 2305 for (std::set<std::string>::const_iterator it = resource.labels_.begin(); it != resource.labels_.end(); ++it)
2289 { 2306 {
2290 labels.append(*it); 2307 labels.append(*it);
2291 } 2308 }
2292 2309
2293 target["Labels"] = labels; 2310 target["Labels"] = labels;
2311 }
2312
2313 // new in Orthanc 1.12.4
2314 if ((expandFlags & ExpandResourceFlags_IncludeAllMetadata) != 0)
2315 {
2316 Json::Value metadata = Json::objectValue;
2317
2318 for (std::map<MetadataType, std::string>::const_iterator it = resource.metadata_.begin(); it != resource.metadata_.end(); ++it)
2319 {
2320 metadata[EnumerationToString(it->first)] = it->second;
2321 }
2322
2323 target["Metadata"] = metadata;
2294 } 2324 }
2295 } 2325 }
2296 2326
2297 2327
2298 static void ComputeInstanceTags(ExpandedResource& resource, 2328 static void ComputeInstanceTags(ExpandedResource& resource,
2535 const std::set<DicomTag>& requestedTags, 2565 const std::set<DicomTag>& requestedTags,
2536 bool allowStorageAccess) 2566 bool allowStorageAccess)
2537 { 2567 {
2538 ExpandedResource resource; 2568 ExpandedResource resource;
2539 2569
2540 if (ExpandResource(resource, publicId, mainDicomTags, instanceId, dicomAsJson, level, requestedTags, ExpandResourceFlags_Default, allowStorageAccess)) 2570 if (ExpandResource(resource, publicId, mainDicomTags, instanceId, dicomAsJson, level, requestedTags, ExpandResourceFlags_DefaultExtract, allowStorageAccess))
2541 { 2571 {
2542 SerializeExpandedResource(target, resource, format, requestedTags); 2572 SerializeExpandedResource(target, resource, format, requestedTags, ExpandResourceFlags_DefaultOutput);
2543 return true; 2573 return true;
2544 } 2574 }
2545 2575
2546 return false; 2576 return false;
2547 } 2577 }
2685 boost::posix_time::time_duration elapsed = nowUtc - serverStartTimeUtc_; 2715 boost::posix_time::time_duration elapsed = nowUtc - serverStartTimeUtc_;
2686 2716
2687 return elapsed.total_seconds(); 2717 return elapsed.total_seconds();
2688 } 2718 }
2689 2719
2720 void ServerContext::AppendFindResponse(Json::Value& target,
2721 const FindResponse::Item& item,
2722 DicomToJsonFormat format,
2723 const std::set<DicomTag>& requestedTags,
2724 bool allowStorageAccess)
2725 {
2726 // convert to ExpandedResource to re-use the serialization code TODO-FIND: check if this is the right way to do. shouldn't we copy the code and finally get rid of ExpandedResource ?
2727 ExpandedResource resource(item);
2728
2729 ExpandResourceFlags expandFlags = ExpandResourceFlags_None;
2730 if (item.HasResponseContent(FindRequest::ResponseContent_Children))
2731 {
2732 expandFlags = static_cast<ExpandResourceFlags>(expandFlags | ExpandResourceFlags_IncludeChildren);
2733 }
2734 if (item.HasResponseContent(FindRequest::ResponseContent_Metadata))
2735 {
2736 expandFlags = static_cast<ExpandResourceFlags>(expandFlags | ExpandResourceFlags_IncludeAllMetadata | ExpandResourceFlags_IncludeMetadata );
2737 }
2738 if (item.HasResponseContent(FindRequest::ResponseContent_MainDicomTags))
2739 {
2740 expandFlags = static_cast<ExpandResourceFlags>(expandFlags | ExpandResourceFlags_IncludeMainDicomTags);
2741 }
2742 if (item.HasResponseContent(FindRequest::ResponseContent_IsStable))
2743 {
2744 expandFlags = static_cast<ExpandResourceFlags>(expandFlags | ExpandResourceFlags_IncludeIsStable);
2745 }
2746 if (item.HasResponseContent(FindRequest::ResponseContent_Labels))
2747 {
2748 expandFlags = static_cast<ExpandResourceFlags>(expandFlags | ExpandResourceFlags_IncludeLabels);
2749 }
2750
2751 Json::Value jsonItem;
2752 SerializeExpandedResource(jsonItem, resource, format, requestedTags, expandFlags);
2753 target.append(jsonItem);
2754 }
2755
2756
2690 } 2757 }