# HG changeset patch # User Sebastien Jodogne # Date 1720803916 -7200 # Node ID 52771e1a8072092416c437cc07f0d524a5160225 # Parent 31eb66eaed86ec33e1b54510df5bd958c51f6d09 removed ServerContext::ExpandResource() diff -r 31eb66eaed86 -r 52771e1a8072 OrthancServer/Sources/ServerContext.cpp --- a/OrthancServer/Sources/ServerContext.cpp Fri Jul 12 18:59:20 2024 +0200 +++ b/OrthancServer/Sources/ServerContext.cpp Fri Jul 12 19:05:16 2024 +0200 @@ -69,12 +69,6 @@ namespace Orthanc { - static void ComputeStudyTags(ExpandedResource& resource, - ServerContext& context, - const std::string& studyPublicId, - const std::set& requestedTags); - - static bool IsUncompressedTransferSyntax(DicomTransferSyntax transferSyntax) { return (transferSyntax == DicomTransferSyntax_LittleEndianImplicit || @@ -1939,600 +1933,6 @@ isUnknownSopClassAccepted_ = accepted; } - - static void SerializeExpandedResource(Json::Value& target, - const ExpandedResource& resource, - DicomToJsonFormat format, - const std::set& requestedTags, - ExpandResourceFlags expandFlags) - { - target = Json::objectValue; - - target["Type"] = GetResourceTypeText(resource.GetLevel(), false, true); - target["ID"] = resource.GetPublicId(); - - if (!resource.parentId_.empty()) - { - switch (resource.GetLevel()) - { - case ResourceType_Patient: - break; - - case ResourceType_Study: - target["ParentPatient"] = resource.parentId_; - break; - - case ResourceType_Series: - target["ParentStudy"] = resource.parentId_; - break; - - case ResourceType_Instance: - target["ParentSeries"] = resource.parentId_; - break; - - default: - throw OrthancException(ErrorCode_InternalError); - } - } - - if ((expandFlags & ExpandResourceFlags_IncludeChildren) != 0) - { - switch (resource.GetLevel()) - { - case ResourceType_Patient: - case ResourceType_Study: - case ResourceType_Series: - { - Json::Value c = Json::arrayValue; - - for (std::list::const_iterator - it = resource.childrenIds_.begin(); it != resource.childrenIds_.end(); ++it) - { - c.append(*it); - } - - if (resource.GetLevel() == ResourceType_Patient) - { - target["Studies"] = c; - } - else if (resource.GetLevel() == ResourceType_Study) - { - target["Series"] = c; - } - else - { - target["Instances"] = c; - } - break; - } - - case ResourceType_Instance: - break; - - default: - throw OrthancException(ErrorCode_InternalError); - } - } - - if ((expandFlags & ExpandResourceFlags_IncludeMetadata) != 0) - { - switch (resource.GetLevel()) - { - case ResourceType_Patient: - case ResourceType_Study: - break; - - case ResourceType_Series: - if (resource.expectedNumberOfInstances_ < 0) - { - target["ExpectedNumberOfInstances"] = Json::nullValue; - } - else - { - target["ExpectedNumberOfInstances"] = resource.expectedNumberOfInstances_; - } - target["Status"] = resource.status_; - break; - - case ResourceType_Instance: - { - target["FileSize"] = static_cast(resource.fileSize_); - target["FileUuid"] = resource.fileUuid_; - - if (resource.indexInSeries_ < 0) - { - target["IndexInSeries"] = Json::nullValue; - } - else - { - target["IndexInSeries"] = resource.indexInSeries_; - } - - break; - } - - default: - throw OrthancException(ErrorCode_InternalError); - } - - if (!resource.anonymizedFrom_.empty()) - { - target["AnonymizedFrom"] = resource.anonymizedFrom_; - } - - if (!resource.modifiedFrom_.empty()) - { - target["ModifiedFrom"] = resource.modifiedFrom_; - } - } - - if (resource.GetLevel() == ResourceType_Patient || - resource.GetLevel() == ResourceType_Study || - resource.GetLevel() == ResourceType_Series) - { - if ((expandFlags & ExpandResourceFlags_IncludeIsStable) != 0) - { - target["IsStable"] = resource.isStable_; - } - - if (!resource.lastUpdate_.empty()) - { - target["LastUpdate"] = resource.lastUpdate_; - } - } - - if ((expandFlags & ExpandResourceFlags_IncludeMainDicomTags) != 0) - { - // serialize tags - - static const char* const MAIN_DICOM_TAGS = "MainDicomTags"; - static const char* const PATIENT_MAIN_DICOM_TAGS = "PatientMainDicomTags"; - - DicomMap mainDicomTags; - resource.GetMainDicomTags().ExtractResourceInformation(mainDicomTags, resource.GetLevel()); - - target[MAIN_DICOM_TAGS] = Json::objectValue; - FromDcmtkBridge::ToJson(target[MAIN_DICOM_TAGS], mainDicomTags, format); - - if (resource.GetLevel() == ResourceType_Study) - { - DicomMap patientMainDicomTags; - resource.GetMainDicomTags().ExtractPatientInformation(patientMainDicomTags); - - target[PATIENT_MAIN_DICOM_TAGS] = Json::objectValue; - FromDcmtkBridge::ToJson(target[PATIENT_MAIN_DICOM_TAGS], patientMainDicomTags, format); - } - - if (requestedTags.size() > 0) - { - static const char* const REQUESTED_TAGS = "RequestedTags"; - - DicomMap tags; - resource.GetMainDicomTags().ExtractTags(tags, requestedTags); - - target[REQUESTED_TAGS] = Json::objectValue; - FromDcmtkBridge::ToJson(target[REQUESTED_TAGS], tags, format); - - } - } - - if ((expandFlags & ExpandResourceFlags_IncludeLabels) != 0) - { - Json::Value labels = Json::arrayValue; - - for (std::set::const_iterator it = resource.labels_.begin(); it != resource.labels_.end(); ++it) - { - labels.append(*it); - } - - target["Labels"] = labels; - } - - // new in Orthanc 1.12.4 - if ((expandFlags & ExpandResourceFlags_IncludeAllMetadata) != 0) - { - Json::Value metadata = Json::objectValue; - - for (std::map::const_iterator it = resource.metadata_.begin(); it != resource.metadata_.end(); ++it) - { - metadata[EnumerationToString(it->first)] = it->second; - } - - target["Metadata"] = metadata; - } - } - - - static void ComputeInstanceTags(ExpandedResource& resource, - ServerContext& context, - const std::string& instancePublicId, - const std::set& requestedTags) - { - if (requestedTags.count(DICOM_TAG_INSTANCE_AVAILABILITY) > 0) - { - resource.GetMainDicomTags().SetValue(DICOM_TAG_INSTANCE_AVAILABILITY, "ONLINE", false); - resource.missingRequestedTags_.erase(DICOM_TAG_INSTANCE_AVAILABILITY); - } - } - - - static void ComputeSeriesTags(ExpandedResource& resource, - ServerContext& context, - const std::string& seriesPublicId, - const std::set& requestedTags) - { - if (requestedTags.count(DICOM_TAG_NUMBER_OF_SERIES_RELATED_INSTANCES) > 0) - { - ServerIndex& index = context.GetIndex(); - std::list instances; - - index.GetChildren(instances, seriesPublicId); - - resource.GetMainDicomTags().SetValue(DICOM_TAG_NUMBER_OF_SERIES_RELATED_INSTANCES, - boost::lexical_cast(instances.size()), false); - resource.missingRequestedTags_.erase(DICOM_TAG_NUMBER_OF_SERIES_RELATED_INSTANCES); - } - } - - static void ComputeStudyTags(ExpandedResource& resource, - ServerContext& context, - const std::string& studyPublicId, - const std::set& requestedTags) - { - ServerIndex& index = context.GetIndex(); - std::list series; - std::list instances; - - bool hasNbRelatedSeries = requestedTags.count(DICOM_TAG_NUMBER_OF_STUDY_RELATED_SERIES) > 0; - bool hasNbRelatedInstances = requestedTags.count(DICOM_TAG_NUMBER_OF_STUDY_RELATED_INSTANCES) > 0; - bool hasModalitiesInStudy = requestedTags.count(DICOM_TAG_MODALITIES_IN_STUDY) > 0; - bool hasSopClassesInStudy = requestedTags.count(DICOM_TAG_SOP_CLASSES_IN_STUDY) > 0; - - index.GetChildren(series, studyPublicId); - - if (hasModalitiesInStudy) - { - std::set values; - - for (std::list::const_iterator - it = series.begin(); it != series.end(); ++it) - { - DicomMap tags; - index.GetMainDicomTags(tags, *it, ResourceType_Series, ResourceType_Series); - - const DicomValue* value = tags.TestAndGetValue(DICOM_TAG_MODALITY); - - if (value != NULL && - !value->IsNull() && - !value->IsBinary()) - { - values.insert(value->GetContent()); - } - } - - std::string modalities; - Toolbox::JoinStrings(modalities, values, "\\"); - - resource.GetMainDicomTags().SetValue(DICOM_TAG_MODALITIES_IN_STUDY, modalities, false); - resource.missingRequestedTags_.erase(DICOM_TAG_MODALITIES_IN_STUDY); - } - - if (hasNbRelatedSeries) - { - resource.GetMainDicomTags().SetValue(DICOM_TAG_NUMBER_OF_STUDY_RELATED_SERIES, - boost::lexical_cast(series.size()), false); - resource.missingRequestedTags_.erase(DICOM_TAG_NUMBER_OF_STUDY_RELATED_SERIES); - } - - if (hasNbRelatedInstances || hasSopClassesInStudy) - { - for (std::list::const_iterator - it = series.begin(); it != series.end(); ++it) - { - std::list seriesInstancesIds; - index.GetChildren(seriesInstancesIds, *it); - - instances.splice(instances.end(), seriesInstancesIds); - } - - if (hasNbRelatedInstances) - { - resource.GetMainDicomTags().SetValue(DICOM_TAG_NUMBER_OF_STUDY_RELATED_INSTANCES, - boost::lexical_cast(instances.size()), false); - resource.missingRequestedTags_.erase(DICOM_TAG_NUMBER_OF_STUDY_RELATED_INSTANCES); - } - - if (hasSopClassesInStudy) - { - std::set values; - - for (std::list::const_iterator - it = instances.begin(); it != instances.end(); ++it) - { - std::string value; - - if (context.LookupOrReconstructMetadata(value, *it, ResourceType_Instance, MetadataType_Instance_SopClassUid)) - { - values.insert(value); - } - } - - if (values.size() > 0) - { - std::string sopClassUids; - Toolbox::JoinStrings(sopClassUids, values, "\\"); - resource.GetMainDicomTags().SetValue(DICOM_TAG_SOP_CLASSES_IN_STUDY, sopClassUids, false); - } - - resource.missingRequestedTags_.erase(DICOM_TAG_SOP_CLASSES_IN_STUDY); - } - } - } - - static void ComputePatientTags(ExpandedResource& resource, - ServerContext& context, - const std::string& patientPublicId, - const std::set& requestedTags) - { - ServerIndex& index = context.GetIndex(); - - std::list studies; - std::list series; - std::list instances; - - bool hasNbRelatedStudies = requestedTags.count(DICOM_TAG_NUMBER_OF_PATIENT_RELATED_STUDIES) > 0; - bool hasNbRelatedSeries = requestedTags.count(DICOM_TAG_NUMBER_OF_PATIENT_RELATED_SERIES) > 0; - bool hasNbRelatedInstances = requestedTags.count(DICOM_TAG_NUMBER_OF_PATIENT_RELATED_INSTANCES) > 0; - - index.GetChildren(studies, patientPublicId); - - if (hasNbRelatedStudies) - { - resource.GetMainDicomTags().SetValue(DICOM_TAG_NUMBER_OF_PATIENT_RELATED_STUDIES, - boost::lexical_cast(studies.size()), false); - resource.missingRequestedTags_.erase(DICOM_TAG_NUMBER_OF_PATIENT_RELATED_STUDIES); - } - - if (hasNbRelatedSeries || hasNbRelatedInstances) - { - for (std::list::const_iterator - it = studies.begin(); it != studies.end(); ++it) - { - std::list thisSeriesIds; - index.GetChildren(thisSeriesIds, *it); - series.splice(series.end(), thisSeriesIds); - } - - if (hasNbRelatedSeries) - { - resource.GetMainDicomTags().SetValue(DICOM_TAG_NUMBER_OF_PATIENT_RELATED_SERIES, - boost::lexical_cast(series.size()), false); - resource.missingRequestedTags_.erase(DICOM_TAG_NUMBER_OF_PATIENT_RELATED_SERIES); - } - } - - if (hasNbRelatedInstances) - { - for (std::list::const_iterator - it = series.begin(); it != series.end(); ++it) - { - std::list thisInstancesIds; - index.GetChildren(thisInstancesIds, *it); - instances.splice(instances.end(), thisInstancesIds); - } - - resource.GetMainDicomTags().SetValue(DICOM_TAG_NUMBER_OF_PATIENT_RELATED_INSTANCES, - boost::lexical_cast(instances.size()), false); - resource.missingRequestedTags_.erase(DICOM_TAG_NUMBER_OF_PATIENT_RELATED_INSTANCES); - } - } - - - static void ComputeTags(ExpandedResource& resource, - ServerContext& context, - const std::string& resourceId, - ResourceType level, - const std::set& requestedTags) - { - if (level == ResourceType_Patient - && DicomMap::HasComputedTags(resource.missingRequestedTags_, ResourceType_Patient)) - { - ComputePatientTags(resource, context, resourceId, requestedTags); - } - - if (level == ResourceType_Study - && DicomMap::HasComputedTags(resource.missingRequestedTags_, ResourceType_Study)) - { - ComputeStudyTags(resource, context, resourceId, requestedTags); - } - - if (level == ResourceType_Series - && DicomMap::HasComputedTags(resource.missingRequestedTags_, ResourceType_Series)) - { - ComputeSeriesTags(resource, context, resourceId, requestedTags); - } - - if (level == ResourceType_Instance - && DicomMap::HasComputedTags(resource.missingRequestedTags_, ResourceType_Instance)) - { - ComputeInstanceTags(resource, context, resourceId, requestedTags); - } - } - - bool ServerContext::ExpandResource(Json::Value& target, - const std::string& publicId, - ResourceType level, - DicomToJsonFormat format, - const std::set& requestedTags, - bool allowStorageAccess) - { - std::string unusedInstanceId; - Json::Value* unusedDicomAsJson = NULL; - DicomMap unusedMainDicomTags; - - return ExpandResource(target, publicId, unusedMainDicomTags, unusedInstanceId, unusedDicomAsJson, level, format, requestedTags, allowStorageAccess); - } - - bool ServerContext::ExpandResource(Json::Value& target, - const std::string& publicId, - const DicomMap& mainDicomTags, // optional: the main dicom tags for the resource (if already available) - const std::string& instanceId, // optional: the id of an instance for the resource (if already available) - const Json::Value* dicomAsJson, // optional: the dicom-as-json for the resource (if already available) - ResourceType level, - DicomToJsonFormat format, - const std::set& requestedTags, - bool allowStorageAccess) - { - ExpandedResource resource; - - if (ExpandResource(resource, publicId, mainDicomTags, instanceId, dicomAsJson, level, requestedTags, ExpandResourceFlags_DefaultExtract, allowStorageAccess)) - { - SerializeExpandedResource(target, resource, format, requestedTags, ExpandResourceFlags_DefaultOutput); - return true; - } - - return false; - } - - bool ServerContext::ExpandResource(ExpandedResource& resource, - const std::string& publicId, - const DicomMap& mainDicomTags, // optional: the main dicom tags for the resource (if already available) - const std::string& instanceId, // optional: the id of an instance for the resource (if already available) - const Json::Value* dicomAsJson, // optional: the dicom-as-json for the resource (if already available) - ResourceType level, - const std::set& requestedTags, - ExpandResourceFlags expandFlags, - bool allowStorageAccess) - { - // first try to get the tags from what is already available - - if ((expandFlags & ExpandResourceFlags_IncludeMainDicomTags) && - mainDicomTags.GetSize() > 0 && - dicomAsJson != NULL) - { - - resource.GetMainDicomTags().Merge(mainDicomTags); - - if (dicomAsJson->isObject()) - { - resource.GetMainDicomTags().FromDicomAsJson(*dicomAsJson); - } - - std::set retrievedTags; - std::set missingTags; - resource.GetMainDicomTags().GetTags(retrievedTags); - - Toolbox::GetMissingsFromSet(missingTags, requestedTags, retrievedTags); - - // if all possible tags have been read, no need to get them from DB anymore - if (missingTags.size() > 0 && DicomMap::HasOnlyComputedTags(missingTags)) - { - resource.missingRequestedTags_ = missingTags; - ComputeTags(resource, *this, publicId, level, requestedTags); - return true; - } - else if (missingTags.size() == 0) - { - expandFlags = static_cast(expandFlags & ~ExpandResourceFlags_IncludeMainDicomTags); - } - - if (missingTags.size() == 0 && expandFlags == ExpandResourceFlags_None) // we have already retrieved anything we need - { - return true; - } - } - - if (expandFlags != ExpandResourceFlags_None && - GetIndex().ExpandResource(resource, publicId, level, requestedTags, - static_cast(expandFlags | ExpandResourceFlags_IncludeMetadata))) // we always need the metadata to get the mainDicomTagsSignature - { - // check the main dicom tags list has not changed since the resource was stored - if (resource.mainDicomTagsSignature_ != DicomMap::GetMainDicomTagsSignature(resource.GetLevel())) - { - OrthancConfiguration::ReaderLock lock; - if (lock.GetConfiguration().IsWarningEnabled(Warnings_002_InconsistentDicomTagsInDb)) - { - LOG(WARNING) << "W002: " << Orthanc::GetResourceTypeText(resource.GetLevel(), false , false) - << " has been stored with another version of Main Dicom Tags list, you should POST to /" - << Orthanc::GetResourceTypeText(resource.GetLevel(), true, false) - << "/" << resource.GetPublicId() - << "/reconstruct to update the list of tags saved in DB. Some MainDicomTags might be missing from this answer."; - } - } - - // possibly merge missing requested tags from dicom-as-json - if (allowStorageAccess && - !resource.missingRequestedTags_.empty() && - !DicomMap::HasOnlyComputedTags(resource.missingRequestedTags_)) - { - OrthancConfiguration::ReaderLock lock; - if (lock.GetConfiguration().IsWarningEnabled(Warnings_001_TagsBeingReadFromStorage)) - { - std::set missingTags; - Toolbox::AppendSets(missingTags, resource.missingRequestedTags_); - for (std::set::const_iterator it = resource.missingRequestedTags_.begin(); it != resource.missingRequestedTags_.end(); ++it) - { - if (DicomMap::IsComputedTag(*it)) - { - missingTags.erase(*it); - } - } - - std::string missings; - FromDcmtkBridge::FormatListOfTags(missings, missingTags); - - LOG(WARNING) << "W001: Accessing Dicom tags from storage when accessing " - << Orthanc::GetResourceTypeText(resource.GetLevel(), false, false) - << " : " << missings; - } - - - std::string instanceId_ = instanceId; - DicomMap tagsFromJson; - - if (dicomAsJson == NULL) - { - if (instanceId_.empty()) - { - if (level == ResourceType_Instance) - { - instanceId_ = publicId; - } - else - { - std::list instancesIds; - GetIndex().GetChildInstances(instancesIds, publicId); - if (instancesIds.size() < 1) - { - throw OrthancException(ErrorCode_InternalError, "ExpandResource: no instances found"); - } - instanceId_ = instancesIds.front(); - } - } - - Json::Value tmpDicomAsJson; - ReadDicomAsJson(tmpDicomAsJson, instanceId_, resource.missingRequestedTags_ /* ignoreTagLength */); // read all tags from DICOM and avoid cropping requested tags - tagsFromJson.FromDicomAsJson(tmpDicomAsJson, false /* append */, true /* parseSequences*/); - } - else - { - tagsFromJson.FromDicomAsJson(*dicomAsJson, false /* append */, true /* parseSequences*/); - } - - resource.GetMainDicomTags().Merge(tagsFromJson); - } - - // compute the requested tags - ComputeTags(resource, *this, publicId, level, requestedTags); - } - else - { - return false; - } - - return true; - } - int64_t ServerContext::GetServerUpTime() const { boost::posix_time::ptime nowUtc = boost::posix_time::second_clock::universal_time(); diff -r 31eb66eaed86 -r 52771e1a8072 OrthancServer/Sources/ServerContext.h --- a/OrthancServer/Sources/ServerContext.h Fri Jul 12 18:59:20 2024 +0200 +++ b/OrthancServer/Sources/ServerContext.h Fri Jul 12 19:05:16 2024 +0200 @@ -561,33 +561,6 @@ void SetUnknownSopClassAccepted(bool accepted); - bool ExpandResource(Json::Value& target, - const std::string& publicId, - ResourceType level, - DicomToJsonFormat format, - const std::set& requestedTags, - bool allowStorageAccess); - - bool ExpandResource(Json::Value& target, - const std::string& publicId, - const DicomMap& mainDicomTags, // optional: the main dicom tags for the resource (if already available) - const std::string& instanceId, // optional: the id of an instance for the resource - const Json::Value* dicomAsJson, // optional: the dicom-as-json for the resource - ResourceType level, - DicomToJsonFormat format, - const std::set& requestedTags, - bool allowStorageAccess); - - bool ExpandResource(ExpandedResource& target, - const std::string& publicId, - const DicomMap& mainDicomTags, // optional: the main dicom tags for the resource (if already available) - const std::string& instanceId, // optional: the id of an instance for the resource - const Json::Value* dicomAsJson, // optional: the dicom-as-json for the resource - ResourceType level, - const std::set& requestedTags, - ExpandResourceFlags expandFlags, - bool allowStorageAccess); - FindStorageAccessMode GetFindStorageAccessMode() const { return findStorageAccessMode_;