Mercurial > hg > orthanc
comparison OrthancServer/Sources/OrthancRestApi/OrthancRestResources.cpp @ 5851:6a4e47163b3c find-refactoring
cleaning OrthancRestResources.cpp
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Tue, 29 Oct 2024 15:21:15 +0000 |
parents | 1980354c8113 |
children |
comparison
equal
deleted
inserted
replaced
5850:1980354c8113 | 5851:6a4e47163b3c |
---|---|
66 static const char* const ARG_WHOLE = "whole"; | 66 static const char* const ARG_WHOLE = "whole"; |
67 | 67 |
68 | 68 |
69 namespace Orthanc | 69 namespace Orthanc |
70 { | 70 { |
71 static ResourceType GetResourceTypeFromUri(const RestApiCall& call) | |
72 { | |
73 assert(!call.GetFullUri().empty()); | |
74 const std::string resourceType = call.GetFullUri() [0]; | |
75 return StringToResourceType(resourceType.c_str()); | |
76 } | |
77 | |
78 | |
71 static std::string GetDocumentationSampleResource(ResourceType type) | 79 static std::string GetDocumentationSampleResource(ResourceType type) |
72 { | 80 { |
73 switch (type) | 81 switch (type) |
74 { | 82 { |
75 case Orthanc::ResourceType_Instance: | 83 case Orthanc::ResourceType_Instance: |
1574 } | 1582 } |
1575 | 1583 |
1576 | 1584 |
1577 static void GetResourceStatistics(RestApiGetCall& call) | 1585 static void GetResourceStatistics(RestApiGetCall& call) |
1578 { | 1586 { |
1579 if (call.IsDocumentation()) | 1587 const ResourceType level = GetResourceTypeFromUri(call); |
1580 { | 1588 |
1581 ResourceType t = StringToResourceType(call.GetFullUri()[0].c_str()); | 1589 if (call.IsDocumentation()) |
1582 std::string r = GetResourceTypeText(t, false /* plural */, false /* upper case */); | 1590 { |
1583 call.GetDocumentation() | 1591 std::string r = GetResourceTypeText(level, false /* plural */, false /* upper case */); |
1584 .SetTag(GetResourceTypeText(t, true /* plural */, true /* upper case */)) | 1592 call.GetDocumentation() |
1593 .SetTag(GetResourceTypeText(level, true /* plural */, true /* upper case */)) | |
1585 .SetSummary("Get " + r + " statistics") | 1594 .SetSummary("Get " + r + " statistics") |
1586 .SetDescription("Get statistics about the given " + r) | 1595 .SetDescription("Get statistics about the given " + r) |
1587 .SetUriArgument("id", "Orthanc identifier of the " + r + " of interest") | 1596 .SetUriArgument("id", "Orthanc identifier of the " + r + " of interest") |
1588 .SetAnswerField("DiskSize", RestApiCallDocumentation::Type_String, | 1597 .SetAnswerField("DiskSize", RestApiCallDocumentation::Type_String, |
1589 "Size of the " + r + " on the disk in bytes, expressed as a string for 64bit compatibility with JSON") | 1598 "Size of the " + r + " on the disk in bytes, expressed as a string for 64bit compatibility with JSON") |
1600 "Size on the disk of the DICOM instances associated with the " + r + ", expressed in megabytes (MB)") | 1609 "Size on the disk of the DICOM instances associated with the " + r + ", expressed in megabytes (MB)") |
1601 .SetAnswerField("DicomUncompressedSize", RestApiCallDocumentation::Type_String, | 1610 .SetAnswerField("DicomUncompressedSize", RestApiCallDocumentation::Type_String, |
1602 "Size on the disk of the uncompressed DICOM instances associated with the " + r + ", expressed in bytes") | 1611 "Size on the disk of the uncompressed DICOM instances associated with the " + r + ", expressed in bytes") |
1603 .SetAnswerField("DicomUncompressedSizeMB", RestApiCallDocumentation::Type_Number, | 1612 .SetAnswerField("DicomUncompressedSizeMB", RestApiCallDocumentation::Type_Number, |
1604 "Size on the disk of the uncompressed DICOM instances associated with the " + r + ", expressed in megabytes (MB)") | 1613 "Size on the disk of the uncompressed DICOM instances associated with the " + r + ", expressed in megabytes (MB)") |
1605 .SetHttpGetSample(GetDocumentationSampleResource(t) + "/statistics", true); | 1614 .SetHttpGetSample(GetDocumentationSampleResource(level) + "/statistics", true); |
1606 | 1615 |
1607 switch (t) | 1616 switch (level) |
1608 { | 1617 { |
1609 // Do NOT add "break" below this point! | 1618 // Do NOT add "break" below this point! |
1610 case ResourceType_Patient: | 1619 case ResourceType_Patient: |
1611 call.GetDocumentation().SetAnswerField("CountStudies", RestApiCallDocumentation::Type_Number, | 1620 call.GetDocumentation().SetAnswerField("CountStudies", RestApiCallDocumentation::Type_Number, |
1612 "Number of child studies within this " + r); | 1621 "Number of child studies within this " + r); |
1671 | 1680 |
1672 | 1681 |
1673 | 1682 |
1674 // Handling of metadata ----------------------------------------------------- | 1683 // Handling of metadata ----------------------------------------------------- |
1675 | 1684 |
1676 static ResourceType GetResourceTypeFromUri(const RestApiCall& call) | |
1677 { | |
1678 assert(!call.GetFullUri().empty()); | |
1679 const std::string resourceType = call.GetFullUri() [0]; | |
1680 return StringToResourceType(resourceType.c_str()); | |
1681 } | |
1682 | |
1683 | |
1684 static void CheckValidResourceType(const RestApiCall& call) | |
1685 { | |
1686 GetResourceTypeFromUri(call); | |
1687 } | |
1688 | |
1689 | |
1690 static void ListMetadata(RestApiGetCall& call) | 1685 static void ListMetadata(RestApiGetCall& call) |
1691 { | 1686 { |
1692 if (call.IsDocumentation()) | 1687 const ResourceType level = GetResourceTypeFromUri(call); |
1693 { | 1688 |
1694 ResourceType t = StringToResourceType(call.GetFullUri()[0].c_str()); | 1689 if (call.IsDocumentation()) |
1695 std::string r = GetResourceTypeText(t, false /* plural */, false /* upper case */); | 1690 { |
1696 call.GetDocumentation() | 1691 std::string r = GetResourceTypeText(level, false /* plural */, false /* upper case */); |
1697 .SetTag(GetResourceTypeText(t, true /* plural */, true /* upper case */)) | 1692 call.GetDocumentation() |
1693 .SetTag(GetResourceTypeText(level, true /* plural */, true /* upper case */)) | |
1698 .SetSummary("List metadata") | 1694 .SetSummary("List metadata") |
1699 .SetDescription("Get the list of metadata that are associated with the given " + r) | 1695 .SetDescription("Get the list of metadata that are associated with the given " + r) |
1700 .SetUriArgument("id", "Orthanc identifier of the " + r + " of interest") | 1696 .SetUriArgument("id", "Orthanc identifier of the " + r + " of interest") |
1701 .SetHttpGetArgument("expand", RestApiCallDocumentation::Type_String, | 1697 .SetHttpGetArgument("expand", RestApiCallDocumentation::Type_String, |
1702 "If present, also retrieve the value of the individual metadata", false) | 1698 "If present, also retrieve the value of the individual metadata", false) |
1703 .SetHttpGetArgument("numeric", RestApiCallDocumentation::Type_String, | 1699 .SetHttpGetArgument("numeric", RestApiCallDocumentation::Type_String, |
1704 "If present, use the numeric identifier of the metadata instead of its symbolic name", false) | 1700 "If present, use the numeric identifier of the metadata instead of its symbolic name", false) |
1705 .AddAnswerType(MimeType_Json, "JSON array containing the names of the available metadata, " | 1701 .AddAnswerType(MimeType_Json, "JSON array containing the names of the available metadata, " |
1706 "or JSON associative array mapping metadata to their values (if `expand` argument is provided)") | 1702 "or JSON associative array mapping metadata to their values (if `expand` argument is provided)") |
1707 .SetHttpGetSample(GetDocumentationSampleResource(t) + "/metadata", true); | 1703 .SetHttpGetSample(GetDocumentationSampleResource(level) + "/metadata", true); |
1708 return; | 1704 return; |
1709 } | 1705 } |
1710 | 1706 |
1711 assert(!call.GetFullUri().empty()); | 1707 assert(!call.GetFullUri().empty()); |
1712 const std::string publicId = call.GetUriComponent("id", ""); | 1708 const std::string publicId = call.GetUriComponent("id", ""); |
1713 ResourceType level = StringToResourceType(call.GetFullUri() [0].c_str()); | |
1714 | 1709 |
1715 typedef std::map<MetadataType, std::string> Metadata; | 1710 typedef std::map<MetadataType, std::string> Metadata; |
1716 | 1711 |
1717 Metadata metadata; | 1712 Metadata metadata; |
1718 OrthancRestApi::GetIndex(call).GetAllMetadata(metadata, publicId, level); | 1713 OrthancRestApi::GetIndex(call).GetAllMetadata(metadata, publicId, level); |
1840 } | 1835 } |
1841 | 1836 |
1842 | 1837 |
1843 static void GetMetadata(RestApiGetCall& call) | 1838 static void GetMetadata(RestApiGetCall& call) |
1844 { | 1839 { |
1845 if (call.IsDocumentation()) | 1840 const ResourceType level = GetResourceTypeFromUri(call); |
1846 { | 1841 |
1847 ResourceType t = StringToResourceType(call.GetFullUri()[0].c_str()); | 1842 if (call.IsDocumentation()) |
1848 std::string r = GetResourceTypeText(t, false /* plural */, false /* upper case */); | 1843 { |
1849 call.GetDocumentation() | 1844 std::string r = GetResourceTypeText(level, false /* plural */, false /* upper case */); |
1850 .SetTag(GetResourceTypeText(t, true /* plural */, true /* upper case */)) | 1845 call.GetDocumentation() |
1846 .SetTag(GetResourceTypeText(level, true /* plural */, true /* upper case */)) | |
1851 .SetSummary("Get metadata") | 1847 .SetSummary("Get metadata") |
1852 .SetDescription("Get the value of a metadata that is associated with the given " + r) | 1848 .SetDescription("Get the value of a metadata that is associated with the given " + r) |
1853 .SetUriArgument("id", "Orthanc identifier of the " + r + " of interest") | 1849 .SetUriArgument("id", "Orthanc identifier of the " + r + " of interest") |
1854 .SetUriArgument("name", "The name of the metadata, or its index (cf. `UserMetadata` configuration option)") | 1850 .SetUriArgument("name", "The name of the metadata, or its index (cf. `UserMetadata` configuration option)") |
1855 .AddAnswerType(MimeType_PlainText, "Value of the metadata") | 1851 .AddAnswerType(MimeType_PlainText, "Value of the metadata") |
1858 return; | 1854 return; |
1859 } | 1855 } |
1860 | 1856 |
1861 assert(!call.GetFullUri().empty()); | 1857 assert(!call.GetFullUri().empty()); |
1862 const std::string publicId = call.GetUriComponent("id", ""); | 1858 const std::string publicId = call.GetUriComponent("id", ""); |
1863 const ResourceType level = StringToResourceType(call.GetFullUri() [0].c_str()); | |
1864 | 1859 |
1865 std::string name = call.GetUriComponent("name", ""); | 1860 std::string name = call.GetUriComponent("name", ""); |
1866 MetadataType metadata = StringToMetadata(name); | 1861 MetadataType metadata = StringToMetadata(name); |
1867 | 1862 |
1868 std::string value; | 1863 std::string value; |
1887 } | 1882 } |
1888 | 1883 |
1889 | 1884 |
1890 static void DeleteMetadata(RestApiDeleteCall& call) | 1885 static void DeleteMetadata(RestApiDeleteCall& call) |
1891 { | 1886 { |
1892 if (call.IsDocumentation()) | 1887 const ResourceType level = GetResourceTypeFromUri(call); |
1893 { | 1888 |
1894 ResourceType t = StringToResourceType(call.GetFullUri()[0].c_str()); | 1889 if (call.IsDocumentation()) |
1895 std::string r = GetResourceTypeText(t, false /* plural */, false /* upper case */); | 1890 { |
1896 call.GetDocumentation() | 1891 std::string r = GetResourceTypeText(level, false /* plural */, false /* upper case */); |
1897 .SetTag(GetResourceTypeText(t, true /* plural */, true /* upper case */)) | 1892 call.GetDocumentation() |
1893 .SetTag(GetResourceTypeText(level, true /* plural */, true /* upper case */)) | |
1898 .SetSummary("Delete metadata") | 1894 .SetSummary("Delete metadata") |
1899 .SetDescription("Delete some metadata associated with the given DICOM " + r + | 1895 .SetDescription("Delete some metadata associated with the given DICOM " + r + |
1900 ". This call will fail if trying to delete a system metadata (i.e. whose index is < 1024).") | 1896 ". This call will fail if trying to delete a system metadata (i.e. whose index is < 1024).") |
1901 .SetUriArgument("id", "Orthanc identifier of the " + r + " of interest") | 1897 .SetUriArgument("id", "Orthanc identifier of the " + r + " of interest") |
1902 .SetUriArgument("name", "The name of the metadata, or its index (cf. `UserMetadata` configuration option)") | 1898 .SetUriArgument("name", "The name of the metadata, or its index (cf. `UserMetadata` configuration option)") |
1903 .SetHttpHeader("If-Match", "Revision of the metadata, to check if its content has not changed and can " | 1899 .SetHttpHeader("If-Match", "Revision of the metadata, to check if its content has not changed and can " |
1904 "be deleted. This header is mandatory if `CheckRevisions` option is `true`."); | 1900 "be deleted. This header is mandatory if `CheckRevisions` option is `true`."); |
1905 return; | 1901 return; |
1906 } | 1902 } |
1907 | 1903 |
1908 CheckValidResourceType(call); | |
1909 const std::string publicId = call.GetUriComponent("id", ""); | 1904 const std::string publicId = call.GetUriComponent("id", ""); |
1910 | 1905 |
1911 std::string name = call.GetUriComponent("name", ""); | 1906 std::string name = call.GetUriComponent("name", ""); |
1912 MetadataType metadata = StringToMetadata(name); | 1907 MetadataType metadata = StringToMetadata(name); |
1913 | 1908 |
1951 } | 1946 } |
1952 | 1947 |
1953 | 1948 |
1954 static void SetMetadata(RestApiPutCall& call) | 1949 static void SetMetadata(RestApiPutCall& call) |
1955 { | 1950 { |
1956 if (call.IsDocumentation()) | 1951 const ResourceType level = GetResourceTypeFromUri(call); |
1957 { | 1952 |
1958 ResourceType t = StringToResourceType(call.GetFullUri()[0].c_str()); | 1953 if (call.IsDocumentation()) |
1959 std::string r = GetResourceTypeText(t, false /* plural */, false /* upper case */); | 1954 { |
1960 call.GetDocumentation() | 1955 std::string r = GetResourceTypeText(level, false /* plural */, false /* upper case */); |
1961 .SetTag(GetResourceTypeText(t, true /* plural */, true /* upper case */)) | 1956 call.GetDocumentation() |
1957 .SetTag(GetResourceTypeText(level, true /* plural */, true /* upper case */)) | |
1962 .SetSummary("Set metadata") | 1958 .SetSummary("Set metadata") |
1963 .SetDescription("Set the value of some metadata in the given DICOM " + r + | 1959 .SetDescription("Set the value of some metadata in the given DICOM " + r + |
1964 ". This call will fail if trying to modify a system metadata (i.e. whose index is < 1024).") | 1960 ". This call will fail if trying to modify a system metadata (i.e. whose index is < 1024).") |
1965 .SetUriArgument("id", "Orthanc identifier of the " + r + " of interest") | 1961 .SetUriArgument("id", "Orthanc identifier of the " + r + " of interest") |
1966 .SetUriArgument("name", "The name of the metadata, or its index (cf. `UserMetadata` configuration option)") | 1962 .SetUriArgument("name", "The name of the metadata, or its index (cf. `UserMetadata` configuration option)") |
1967 .AddRequestType(MimeType_PlainText, "String value of the metadata") | 1963 .AddRequestType(MimeType_PlainText, "String value of the metadata") |
1968 .SetHttpHeader("If-Match", "Revision of the metadata, if this is not the first time this metadata is set."); | 1964 .SetHttpHeader("If-Match", "Revision of the metadata, if this is not the first time this metadata is set."); |
1969 return; | 1965 return; |
1970 } | 1966 } |
1971 | 1967 |
1972 CheckValidResourceType(call); | |
1973 | |
1974 std::string publicId = call.GetUriComponent("id", ""); | 1968 std::string publicId = call.GetUriComponent("id", ""); |
1975 std::string name = call.GetUriComponent("name", ""); | 1969 std::string name = call.GetUriComponent("name", ""); |
1976 MetadataType metadata = StringToMetadata(name); | 1970 MetadataType metadata = StringToMetadata(name); |
1977 | 1971 |
1978 std::string value; | 1972 std::string value; |
2016 | 2010 |
2017 // Handling of labels ------------------------------------------------------- | 2011 // Handling of labels ------------------------------------------------------- |
2018 | 2012 |
2019 static void ListLabels(RestApiGetCall& call) | 2013 static void ListLabels(RestApiGetCall& call) |
2020 { | 2014 { |
2021 if (call.IsDocumentation()) | 2015 const ResourceType level = GetResourceTypeFromUri(call); |
2022 { | 2016 |
2023 ResourceType t = StringToResourceType(call.GetFullUri()[0].c_str()); | 2017 if (call.IsDocumentation()) |
2024 std::string r = GetResourceTypeText(t, false /* plural */, false /* upper case */); | 2018 { |
2025 call.GetDocumentation() | 2019 std::string r = GetResourceTypeText(level, false /* plural */, false /* upper case */); |
2026 .SetTag(GetResourceTypeText(t, true /* plural */, true /* upper case */)) | 2020 call.GetDocumentation() |
2021 .SetTag(GetResourceTypeText(level, true /* plural */, true /* upper case */)) | |
2027 .SetSummary("List labels") | 2022 .SetSummary("List labels") |
2028 .SetDescription("Get the labels that are associated with the given " + r + " (new in Orthanc 1.12.0)") | 2023 .SetDescription("Get the labels that are associated with the given " + r + " (new in Orthanc 1.12.0)") |
2029 .SetUriArgument("id", "Orthanc identifier of the " + r + " of interest") | 2024 .SetUriArgument("id", "Orthanc identifier of the " + r + " of interest") |
2030 .AddAnswerType(MimeType_Json, "JSON array containing the names of the labels") | 2025 .AddAnswerType(MimeType_Json, "JSON array containing the names of the labels") |
2031 .SetHttpGetSample(GetDocumentationSampleResource(t) + "/labels", true); | 2026 .SetHttpGetSample(GetDocumentationSampleResource(level) + "/labels", true); |
2032 return; | 2027 return; |
2033 } | 2028 } |
2034 | 2029 |
2035 assert(!call.GetFullUri().empty()); | |
2036 const std::string publicId = call.GetUriComponent("id", ""); | 2030 const std::string publicId = call.GetUriComponent("id", ""); |
2037 ResourceType level = StringToResourceType(call.GetFullUri() [0].c_str()); | |
2038 | 2031 |
2039 std::set<std::string> labels; | 2032 std::set<std::string> labels; |
2040 OrthancRestApi::GetIndex(call).ListLabels(labels, publicId, level); | 2033 OrthancRestApi::GetIndex(call).ListLabels(labels, publicId, level); |
2041 | 2034 |
2042 Json::Value result = Json::arrayValue; | 2035 Json::Value result = Json::arrayValue; |
2050 } | 2043 } |
2051 | 2044 |
2052 | 2045 |
2053 static void GetLabel(RestApiGetCall& call) | 2046 static void GetLabel(RestApiGetCall& call) |
2054 { | 2047 { |
2055 if (call.IsDocumentation()) | 2048 const ResourceType level = GetResourceTypeFromUri(call); |
2056 { | 2049 |
2057 ResourceType t = StringToResourceType(call.GetFullUri()[0].c_str()); | 2050 if (call.IsDocumentation()) |
2058 std::string r = GetResourceTypeText(t, false /* plural */, false /* upper case */); | 2051 { |
2059 call.GetDocumentation() | 2052 std::string r = GetResourceTypeText(level, false /* plural */, false /* upper case */); |
2060 .SetTag(GetResourceTypeText(t, true /* plural */, true /* upper case */)) | 2053 call.GetDocumentation() |
2054 .SetTag(GetResourceTypeText(level, true /* plural */, true /* upper case */)) | |
2061 .SetSummary("Test label") | 2055 .SetSummary("Test label") |
2062 .SetDescription("Test whether the " + r + " is associated with the given label") | 2056 .SetDescription("Test whether the " + r + " is associated with the given label") |
2063 .SetUriArgument("id", "Orthanc identifier of the " + r + " of interest") | 2057 .SetUriArgument("id", "Orthanc identifier of the " + r + " of interest") |
2064 .SetUriArgument("label", "The label of interest") | 2058 .SetUriArgument("label", "The label of interest") |
2065 .AddAnswerType(MimeType_PlainText, "Empty string is returned in the case of presence, error 404 in the case of absence"); | 2059 .AddAnswerType(MimeType_PlainText, "Empty string is returned in the case of presence, error 404 in the case of absence"); |
2066 return; | 2060 return; |
2067 } | 2061 } |
2068 | 2062 |
2069 CheckValidResourceType(call); | |
2070 | |
2071 assert(!call.GetFullUri().empty()); | |
2072 const std::string publicId = call.GetUriComponent("id", ""); | 2063 const std::string publicId = call.GetUriComponent("id", ""); |
2073 const ResourceType level = StringToResourceType(call.GetFullUri() [0].c_str()); | |
2074 | 2064 |
2075 std::string label = call.GetUriComponent("label", ""); | 2065 std::string label = call.GetUriComponent("label", ""); |
2076 | 2066 |
2077 std::set<std::string> labels; | 2067 std::set<std::string> labels; |
2078 OrthancRestApi::GetIndex(call).ListLabels(labels, publicId, level); | 2068 OrthancRestApi::GetIndex(call).ListLabels(labels, publicId, level); |
2084 } | 2074 } |
2085 | 2075 |
2086 | 2076 |
2087 static void AddLabel(RestApiPutCall& call) | 2077 static void AddLabel(RestApiPutCall& call) |
2088 { | 2078 { |
2089 if (call.IsDocumentation()) | 2079 const ResourceType level = GetResourceTypeFromUri(call); |
2090 { | 2080 |
2091 ResourceType t = StringToResourceType(call.GetFullUri()[0].c_str()); | 2081 if (call.IsDocumentation()) |
2092 std::string r = GetResourceTypeText(t, false /* plural */, false /* upper case */); | 2082 { |
2093 call.GetDocumentation() | 2083 std::string r = GetResourceTypeText(level, false /* plural */, false /* upper case */); |
2094 .SetTag(GetResourceTypeText(t, true /* plural */, true /* upper case */)) | 2084 call.GetDocumentation() |
2085 .SetTag(GetResourceTypeText(level, true /* plural */, true /* upper case */)) | |
2095 .SetSummary("Add label") | 2086 .SetSummary("Add label") |
2096 .SetDescription("Associate a label with a " + r) | 2087 .SetDescription("Associate a label with a " + r) |
2097 .SetUriArgument("id", "Orthanc identifier of the " + r + " of interest") | 2088 .SetUriArgument("id", "Orthanc identifier of the " + r + " of interest") |
2098 .SetUriArgument("label", "The label to be added"); | 2089 .SetUriArgument("label", "The label to be added"); |
2099 return; | 2090 return; |
2100 } | 2091 } |
2101 | 2092 |
2102 CheckValidResourceType(call); | |
2103 | |
2104 std::string publicId = call.GetUriComponent("id", ""); | 2093 std::string publicId = call.GetUriComponent("id", ""); |
2105 const ResourceType level = StringToResourceType(call.GetFullUri() [0].c_str()); | |
2106 | 2094 |
2107 std::string label = call.GetUriComponent("label", ""); | 2095 std::string label = call.GetUriComponent("label", ""); |
2108 OrthancRestApi::GetIndex(call).ModifyLabel(publicId, level, label, StatelessDatabaseOperations::LabelOperation_Add); | 2096 OrthancRestApi::GetIndex(call).ModifyLabel(publicId, level, label, StatelessDatabaseOperations::LabelOperation_Add); |
2109 | 2097 |
2110 call.GetOutput().AnswerBuffer("", MimeType_PlainText); | 2098 call.GetOutput().AnswerBuffer("", MimeType_PlainText); |
2111 } | 2099 } |
2112 | 2100 |
2113 | 2101 |
2114 static void RemoveLabel(RestApiDeleteCall& call) | 2102 static void RemoveLabel(RestApiDeleteCall& call) |
2115 { | 2103 { |
2116 if (call.IsDocumentation()) | 2104 const ResourceType level = GetResourceTypeFromUri(call); |
2117 { | 2105 |
2118 ResourceType t = StringToResourceType(call.GetFullUri()[0].c_str()); | 2106 if (call.IsDocumentation()) |
2119 std::string r = GetResourceTypeText(t, false /* plural */, false /* upper case */); | 2107 { |
2120 call.GetDocumentation() | 2108 std::string r = GetResourceTypeText(level, false /* plural */, false /* upper case */); |
2121 .SetTag(GetResourceTypeText(t, true /* plural */, true /* upper case */)) | 2109 call.GetDocumentation() |
2110 .SetTag(GetResourceTypeText(level, true /* plural */, true /* upper case */)) | |
2122 .SetSummary("Remove label") | 2111 .SetSummary("Remove label") |
2123 .SetDescription("Remove a label associated with a " + r) | 2112 .SetDescription("Remove a label associated with a " + r) |
2124 .SetUriArgument("id", "Orthanc identifier of the " + r + " of interest") | 2113 .SetUriArgument("id", "Orthanc identifier of the " + r + " of interest") |
2125 .SetUriArgument("label", "The label to be removed"); | 2114 .SetUriArgument("label", "The label to be removed"); |
2126 return; | 2115 return; |
2127 } | 2116 } |
2128 | 2117 |
2129 CheckValidResourceType(call); | |
2130 | |
2131 std::string publicId = call.GetUriComponent("id", ""); | 2118 std::string publicId = call.GetUriComponent("id", ""); |
2132 const ResourceType level = StringToResourceType(call.GetFullUri() [0].c_str()); | |
2133 | 2119 |
2134 std::string label = call.GetUriComponent("label", ""); | 2120 std::string label = call.GetUriComponent("label", ""); |
2135 OrthancRestApi::GetIndex(call).ModifyLabel(publicId, level, label, StatelessDatabaseOperations::LabelOperation_Remove); | 2121 OrthancRestApi::GetIndex(call).ModifyLabel(publicId, level, label, StatelessDatabaseOperations::LabelOperation_Remove); |
2136 | 2122 |
2137 call.GetOutput().AnswerBuffer("", MimeType_PlainText); | 2123 call.GetOutput().AnswerBuffer("", MimeType_PlainText); |
2140 | 2126 |
2141 // Handling of attached files ----------------------------------------------- | 2127 // Handling of attached files ----------------------------------------------- |
2142 | 2128 |
2143 static void ListAttachments(RestApiGetCall& call) | 2129 static void ListAttachments(RestApiGetCall& call) |
2144 { | 2130 { |
2145 if (call.IsDocumentation()) | 2131 const ResourceType level = GetResourceTypeFromUri(call); |
2146 { | 2132 |
2147 ResourceType t = StringToResourceType(call.GetFullUri()[0].c_str()); | 2133 if (call.IsDocumentation()) |
2148 std::string r = GetResourceTypeText(t, false /* plural */, false /* upper case */); | 2134 { |
2149 call.GetDocumentation() | 2135 std::string r = GetResourceTypeText(level, false /* plural */, false /* upper case */); |
2150 .SetTag(GetResourceTypeText(t, true /* plural */, true /* upper case */)) | 2136 call.GetDocumentation() |
2137 .SetTag(GetResourceTypeText(level, true /* plural */, true /* upper case */)) | |
2151 .SetSummary("List attachments") | 2138 .SetSummary("List attachments") |
2152 .SetDescription("Get the list of attachments that are associated with the given " + r) | 2139 .SetDescription("Get the list of attachments that are associated with the given " + r) |
2153 .SetUriArgument("id", "Orthanc identifier of the " + r + " of interest") | 2140 .SetUriArgument("id", "Orthanc identifier of the " + r + " of interest") |
2154 .SetHttpGetArgument("full", RestApiCallDocumentation::Type_String, | 2141 .SetHttpGetArgument("full", RestApiCallDocumentation::Type_String, |
2155 "If present, retrieve the attachments list and their numerical ids", false) | 2142 "If present, retrieve the attachments list and their numerical ids", false) |
2156 .AddAnswerType(MimeType_Json, "JSON array containing the names of the attachments") | 2143 .AddAnswerType(MimeType_Json, "JSON array containing the names of the attachments") |
2157 .SetHttpGetSample(GetDocumentationSampleResource(t) + "/attachments", true); | 2144 .SetHttpGetSample(GetDocumentationSampleResource(level) + "/attachments", true); |
2158 return; | 2145 return; |
2159 } | 2146 } |
2160 | 2147 |
2161 const std::string resourceType = call.GetFullUri() [0]; | |
2162 const std::string publicId = call.GetUriComponent("id", ""); | 2148 const std::string publicId = call.GetUriComponent("id", ""); |
2163 std::set<FileContentType> attachments; | 2149 std::set<FileContentType> attachments; |
2164 OrthancRestApi::GetIndex(call).ListAvailableAttachments(attachments, publicId, StringToResourceType(resourceType.c_str())); | 2150 OrthancRestApi::GetIndex(call).ListAvailableAttachments(attachments, publicId, level); |
2165 | 2151 |
2166 Json::Value result; | 2152 Json::Value result; |
2167 | 2153 |
2168 if (call.HasArgument("full")) | 2154 if (call.HasArgument("full")) |
2169 { | 2155 { |
2170 result = Json::objectValue; | 2156 result = Json::objectValue; |
2171 | 2157 |
2172 for (std::set<FileContentType>::const_iterator | 2158 for (std::set<FileContentType>::const_iterator |
2173 it = attachments.begin(); it != attachments.end(); ++it) | 2159 it = attachments.begin(); it != attachments.end(); ++it) |
2174 { | 2160 { |
2175 std::string key = EnumerationToString(*it); | 2161 std::string key = EnumerationToString(*it); |
2176 result[key] = static_cast<uint16_t>(*it); | 2162 result[key] = static_cast<uint16_t>(*it); |
2177 } | 2163 } |
2178 } | 2164 } |
2179 else | 2165 else |
2180 { | 2166 { |
2181 result = Json::arrayValue; | 2167 result = Json::arrayValue; |
2182 | 2168 |
2183 for (std::set<FileContentType>::const_iterator | 2169 for (std::set<FileContentType>::const_iterator |
2184 it = attachments.begin(); it != attachments.end(); ++it) | 2170 it = attachments.begin(); it != attachments.end(); ++it) |
2185 { | 2171 { |
2186 result.append(EnumerationToString(*it)); | 2172 result.append(EnumerationToString(*it)); |
2187 } | 2173 } |
2188 } | 2174 } |
2189 | 2175 |
2204 | 2190 |
2205 static bool GetAttachmentInfo(FileInfo& info, | 2191 static bool GetAttachmentInfo(FileInfo& info, |
2206 ResourceType level, | 2192 ResourceType level, |
2207 RestApiGetCall& call) | 2193 RestApiGetCall& call) |
2208 { | 2194 { |
2209 CheckValidResourceType(call); | |
2210 | |
2211 const std::string publicId = call.GetUriComponent("id", ""); | 2195 const std::string publicId = call.GetUriComponent("id", ""); |
2212 const std::string name = call.GetUriComponent("name", ""); | 2196 const std::string name = call.GetUriComponent("name", ""); |
2213 FileContentType contentType = StringToContentType(name); | 2197 FileContentType contentType = StringToContentType(name); |
2214 | 2198 |
2215 int64_t revision; | 2199 int64_t revision; |
2238 } | 2222 } |
2239 | 2223 |
2240 | 2224 |
2241 static void GetAttachmentOperations(RestApiGetCall& call) | 2225 static void GetAttachmentOperations(RestApiGetCall& call) |
2242 { | 2226 { |
2243 const ResourceType t = GetResourceTypeFromUri(call); | 2227 const ResourceType level = GetResourceTypeFromUri(call); |
2244 | 2228 |
2245 if (call.IsDocumentation()) | 2229 if (call.IsDocumentation()) |
2246 { | 2230 { |
2247 ResourceType t = StringToResourceType(call.GetFullUri()[0].c_str()); | 2231 std::string r = GetResourceTypeText(level, false /* plural */, false /* upper case */); |
2248 std::string r = GetResourceTypeText(t, false /* plural */, false /* upper case */); | |
2249 AddAttachmentDocumentation(call, r); | 2232 AddAttachmentDocumentation(call, r); |
2250 call.GetDocumentation() | 2233 call.GetDocumentation() |
2251 .SetTag("Other") | 2234 .SetTag("Other") |
2252 .SetSummary("List operations on attachments") | 2235 .SetSummary("List operations on attachments") |
2253 .SetDescription("Get the list of the operations that are available for attachments associated with the given " + r) | 2236 .SetDescription("Get the list of the operations that are available for attachments associated with the given " + r) |
2255 .SetHttpGetSample("https://orthanc.uclouvain.be/demo/instances/6582b1c0-292ad5ab-ba0f088f-f7a1766f-9a29a54f/attachments/dicom", true); | 2238 .SetHttpGetSample("https://orthanc.uclouvain.be/demo/instances/6582b1c0-292ad5ab-ba0f088f-f7a1766f-9a29a54f/attachments/dicom", true); |
2256 return; | 2239 return; |
2257 } | 2240 } |
2258 | 2241 |
2259 FileInfo info; | 2242 FileInfo info; |
2260 if (GetAttachmentInfo(info, t, call)) | 2243 if (GetAttachmentInfo(info, level, call)) |
2261 { | 2244 { |
2262 Json::Value operations = Json::arrayValue; | 2245 Json::Value operations = Json::arrayValue; |
2263 | 2246 |
2264 operations.append("compress"); | 2247 operations.append("compress"); |
2265 operations.append("compressed-data"); | 2248 operations.append("compressed-data"); |
2294 | 2277 |
2295 | 2278 |
2296 template <int uncompress> | 2279 template <int uncompress> |
2297 static void GetAttachmentData(RestApiGetCall& call) | 2280 static void GetAttachmentData(RestApiGetCall& call) |
2298 { | 2281 { |
2299 const ResourceType t = GetResourceTypeFromUri(call); | 2282 const ResourceType level = GetResourceTypeFromUri(call); |
2300 | 2283 |
2301 if (call.IsDocumentation()) | 2284 if (call.IsDocumentation()) |
2302 { | 2285 { |
2303 std::string r = GetResourceTypeText(t, false /* plural */, false /* upper case */); | 2286 std::string r = GetResourceTypeText(level, false /* plural */, false /* upper case */); |
2304 call.GetDocumentation() | 2287 call.GetDocumentation() |
2305 .SetTag(GetResourceTypeText(t, true /* plural */, true /* upper case */)) | 2288 .SetTag(GetResourceTypeText(level, true /* plural */, true /* upper case */)) |
2306 .SetSummary("Get attachment" + std::string(uncompress ? "" : " (no decompression)")) | 2289 .SetSummary("Get attachment" + std::string(uncompress ? "" : " (no decompression)")) |
2307 .SetDescription("Get the (binary) content of one attachment associated with the given " + r + | 2290 .SetDescription("Get the (binary) content of one attachment associated with the given " + r + |
2308 std::string(uncompress ? "" : ". The attachment will not be decompressed if `StorageCompression` is `true`.")) | 2291 std::string(uncompress ? "" : ". The attachment will not be decompressed if `StorageCompression` is `true`.")) |
2309 .SetUriArgument("id", "Orthanc identifier of the " + r + " of interest") | 2292 .SetUriArgument("id", "Orthanc identifier of the " + r + " of interest") |
2310 .SetUriArgument("name", "The name of the attachment, or its index (cf. `UserContentType` configuration option)") | 2293 .SetUriArgument("name", "The name of the attachment, or its index (cf. `UserContentType` configuration option)") |
2314 return; | 2297 return; |
2315 } | 2298 } |
2316 | 2299 |
2317 ServerContext& context = OrthancRestApi::GetContext(call); | 2300 ServerContext& context = OrthancRestApi::GetContext(call); |
2318 | 2301 |
2319 CheckValidResourceType(call); | |
2320 | |
2321 std::string publicId = call.GetUriComponent("id", ""); | 2302 std::string publicId = call.GetUriComponent("id", ""); |
2322 FileContentType type = StringToContentType(call.GetUriComponent("name", "")); | 2303 FileContentType type = StringToContentType(call.GetUriComponent("name", "")); |
2323 | 2304 |
2324 FileInfo info; | 2305 FileInfo info; |
2325 if (GetAttachmentInfo(info, t, call)) | 2306 if (GetAttachmentInfo(info, level, call)) |
2326 { | 2307 { |
2327 // NB: "SetAttachmentETag()" is already invoked by "GetAttachmentInfo()" | 2308 // NB: "SetAttachmentETag()" is already invoked by "GetAttachmentInfo()" |
2328 | 2309 |
2329 if (uncompress) | 2310 if (uncompress) |
2330 { | 2311 { |
2331 context.AnswerAttachment(call.GetOutput(), t, publicId, type); | 2312 context.AnswerAttachment(call.GetOutput(), level, publicId, type); |
2332 } | 2313 } |
2333 else | 2314 else |
2334 { | 2315 { |
2335 // Return the raw data (possibly compressed), as stored on the filesystem | 2316 // Return the raw data (possibly compressed), as stored on the filesystem |
2336 std::string content; | 2317 std::string content; |
2337 std::string attachmentId; | 2318 std::string attachmentId; |
2338 int64_t revision; | 2319 int64_t revision; |
2339 context.ReadAttachment(content, revision, attachmentId, t, publicId, type, false, true /* skipCache when you absolutely need the compressed data */); | 2320 context.ReadAttachment(content, revision, attachmentId, level, publicId, type, false, true /* skipCache when you absolutely need the compressed data */); |
2340 | 2321 |
2341 int64_t userRevision; | 2322 int64_t userRevision; |
2342 std::string userMD5; | 2323 std::string userMD5; |
2343 if (GetRevisionHeader(userRevision, userMD5, call, "If-None-Match") && | 2324 if (GetRevisionHeader(userRevision, userMD5, call, "If-None-Match") && |
2344 revision == userRevision && | 2325 revision == userRevision && |
2355 } | 2336 } |
2356 | 2337 |
2357 | 2338 |
2358 static void GetAttachmentSize(RestApiGetCall& call) | 2339 static void GetAttachmentSize(RestApiGetCall& call) |
2359 { | 2340 { |
2360 const ResourceType t = GetResourceTypeFromUri(call); | 2341 const ResourceType level = GetResourceTypeFromUri(call); |
2361 | 2342 |
2362 if (call.IsDocumentation()) | 2343 if (call.IsDocumentation()) |
2363 { | 2344 { |
2364 std::string r = GetResourceTypeText(t, false /* plural */, false /* upper case */); | 2345 std::string r = GetResourceTypeText(level, false /* plural */, false /* upper case */); |
2365 AddAttachmentDocumentation(call, r); | 2346 AddAttachmentDocumentation(call, r); |
2366 call.GetDocumentation() | 2347 call.GetDocumentation() |
2367 .SetTag(GetResourceTypeText(t, true /* plural */, true /* upper case */)) | 2348 .SetTag(GetResourceTypeText(level, true /* plural */, true /* upper case */)) |
2368 .SetSummary("Get size of attachment") | 2349 .SetSummary("Get size of attachment") |
2369 .SetDescription("Get the size of one attachment associated with the given " + r) | 2350 .SetDescription("Get the size of one attachment associated with the given " + r) |
2370 .AddAnswerType(MimeType_PlainText, "The size of the attachment"); | 2351 .AddAnswerType(MimeType_PlainText, "The size of the attachment"); |
2371 return; | 2352 return; |
2372 } | 2353 } |
2373 | 2354 |
2374 FileInfo info; | 2355 FileInfo info; |
2375 if (GetAttachmentInfo(info, t, call)) | 2356 if (GetAttachmentInfo(info, level, call)) |
2376 { | 2357 { |
2377 call.GetOutput().AnswerBuffer(boost::lexical_cast<std::string>(info.GetUncompressedSize()), MimeType_PlainText); | 2358 call.GetOutput().AnswerBuffer(boost::lexical_cast<std::string>(info.GetUncompressedSize()), MimeType_PlainText); |
2378 } | 2359 } |
2379 } | 2360 } |
2380 | 2361 |
2381 static void GetAttachmentInfo(RestApiGetCall& call) | 2362 static void GetAttachmentInfo(RestApiGetCall& call) |
2382 { | 2363 { |
2383 const ResourceType t = GetResourceTypeFromUri(call); | 2364 const ResourceType level = GetResourceTypeFromUri(call); |
2384 | 2365 |
2385 if (call.IsDocumentation()) | 2366 if (call.IsDocumentation()) |
2386 { | 2367 { |
2387 std::string r = GetResourceTypeText(t, false /* plural */, false /* upper case */); | 2368 std::string r = GetResourceTypeText(level, false /* plural */, false /* upper case */); |
2388 AddAttachmentDocumentation(call, r); | 2369 AddAttachmentDocumentation(call, r); |
2389 call.GetDocumentation() | 2370 call.GetDocumentation() |
2390 .SetTag(GetResourceTypeText(t, true /* plural */, true /* upper case */)) | 2371 .SetTag(GetResourceTypeText(level, true /* plural */, true /* upper case */)) |
2391 .SetSummary("Get info about the attachment") | 2372 .SetSummary("Get info about the attachment") |
2392 .SetDescription("Get all the information about the attachment associated with the given " + r) | 2373 .SetDescription("Get all the information about the attachment associated with the given " + r) |
2393 .AddAnswerType(MimeType_Json, "JSON object containing the information about the attachment") | 2374 .AddAnswerType(MimeType_Json, "JSON object containing the information about the attachment") |
2394 .SetHttpGetSample("https://orthanc.uclouvain.be/demo/instances/7c92ce8e-bbf67ed2-ffa3b8c1-a3b35d94-7ff3ae26/attachments/dicom/info", true); | 2375 .SetHttpGetSample("https://orthanc.uclouvain.be/demo/instances/7c92ce8e-bbf67ed2-ffa3b8c1-a3b35d94-7ff3ae26/attachments/dicom/info", true); |
2395 return; | 2376 return; |
2396 } | 2377 } |
2397 | 2378 |
2398 FileInfo info; | 2379 FileInfo info; |
2399 if (GetAttachmentInfo(info, t, call)) | 2380 if (GetAttachmentInfo(info, level, call)) |
2400 { | 2381 { |
2401 Json::Value result = Json::objectValue; | 2382 Json::Value result = Json::objectValue; |
2402 result["Uuid"] = info.GetUuid(); | 2383 result["Uuid"] = info.GetUuid(); |
2403 result["ContentType"] = info.GetContentType(); | 2384 result["ContentType"] = info.GetContentType(); |
2404 result["UncompressedSize"] = Json::Value::UInt64(info.GetUncompressedSize()); | 2385 result["UncompressedSize"] = Json::Value::UInt64(info.GetUncompressedSize()); |
2410 } | 2391 } |
2411 } | 2392 } |
2412 | 2393 |
2413 static void GetAttachmentCompressedSize(RestApiGetCall& call) | 2394 static void GetAttachmentCompressedSize(RestApiGetCall& call) |
2414 { | 2395 { |
2415 const ResourceType t = GetResourceTypeFromUri(call); | 2396 const ResourceType level = GetResourceTypeFromUri(call); |
2416 | 2397 |
2417 if (call.IsDocumentation()) | 2398 if (call.IsDocumentation()) |
2418 { | 2399 { |
2419 std::string r = GetResourceTypeText(t, false /* plural */, false /* upper case */); | 2400 std::string r = GetResourceTypeText(level, false /* plural */, false /* upper case */); |
2420 AddAttachmentDocumentation(call, r); | 2401 AddAttachmentDocumentation(call, r); |
2421 call.GetDocumentation() | 2402 call.GetDocumentation() |
2422 .SetTag(GetResourceTypeText(t, true /* plural */, true /* upper case */)) | 2403 .SetTag(GetResourceTypeText(level, true /* plural */, true /* upper case */)) |
2423 .SetSummary("Get size of attachment on disk") | 2404 .SetSummary("Get size of attachment on disk") |
2424 .SetDescription("Get the size of one attachment associated with the given " + r + ", as stored on the disk. " | 2405 .SetDescription("Get the size of one attachment associated with the given " + r + ", as stored on the disk. " |
2425 "This is different from `.../size` iff `EnableStorage` is `true`.") | 2406 "This is different from `.../size` iff `EnableStorage` is `true`.") |
2426 .AddAnswerType(MimeType_PlainText, "The size of the attachment, as stored on the disk"); | 2407 .AddAnswerType(MimeType_PlainText, "The size of the attachment, as stored on the disk"); |
2427 return; | 2408 return; |
2428 } | 2409 } |
2429 | 2410 |
2430 FileInfo info; | 2411 FileInfo info; |
2431 if (GetAttachmentInfo(info, t, call)) | 2412 if (GetAttachmentInfo(info, level, call)) |
2432 { | 2413 { |
2433 call.GetOutput().AnswerBuffer(boost::lexical_cast<std::string>(info.GetCompressedSize()), MimeType_PlainText); | 2414 call.GetOutput().AnswerBuffer(boost::lexical_cast<std::string>(info.GetCompressedSize()), MimeType_PlainText); |
2434 } | 2415 } |
2435 } | 2416 } |
2436 | 2417 |
2437 | 2418 |
2438 static void GetAttachmentMD5(RestApiGetCall& call) | 2419 static void GetAttachmentMD5(RestApiGetCall& call) |
2439 { | 2420 { |
2440 const ResourceType t = GetResourceTypeFromUri(call); | 2421 const ResourceType level = GetResourceTypeFromUri(call); |
2441 | 2422 |
2442 if (call.IsDocumentation()) | 2423 if (call.IsDocumentation()) |
2443 { | 2424 { |
2444 std::string r = GetResourceTypeText(t, false /* plural */, false /* upper case */); | 2425 std::string r = GetResourceTypeText(level, false /* plural */, false /* upper case */); |
2445 AddAttachmentDocumentation(call, r); | 2426 AddAttachmentDocumentation(call, r); |
2446 call.GetDocumentation() | 2427 call.GetDocumentation() |
2447 .SetTag(GetResourceTypeText(t, true /* plural */, true /* upper case */)) | 2428 .SetTag(GetResourceTypeText(level, true /* plural */, true /* upper case */)) |
2448 .SetSummary("Get MD5 of attachment") | 2429 .SetSummary("Get MD5 of attachment") |
2449 .SetDescription("Get the MD5 hash of one attachment associated with the given " + r) | 2430 .SetDescription("Get the MD5 hash of one attachment associated with the given " + r) |
2450 .AddAnswerType(MimeType_PlainText, "The MD5 of the attachment"); | 2431 .AddAnswerType(MimeType_PlainText, "The MD5 of the attachment"); |
2451 return; | 2432 return; |
2452 } | 2433 } |
2453 | 2434 |
2454 FileInfo info; | 2435 FileInfo info; |
2455 if (GetAttachmentInfo(info, t, call) && | 2436 if (GetAttachmentInfo(info, level, call) && |
2456 info.GetUncompressedMD5() != "") | 2437 info.GetUncompressedMD5() != "") |
2457 { | 2438 { |
2458 call.GetOutput().AnswerBuffer(boost::lexical_cast<std::string>(info.GetUncompressedMD5()), MimeType_PlainText); | 2439 call.GetOutput().AnswerBuffer(boost::lexical_cast<std::string>(info.GetUncompressedMD5()), MimeType_PlainText); |
2459 } | 2440 } |
2460 } | 2441 } |
2461 | 2442 |
2462 | 2443 |
2463 static void GetAttachmentCompressedMD5(RestApiGetCall& call) | 2444 static void GetAttachmentCompressedMD5(RestApiGetCall& call) |
2464 { | 2445 { |
2465 const ResourceType t = GetResourceTypeFromUri(call); | 2446 const ResourceType level = GetResourceTypeFromUri(call); |
2466 | 2447 |
2467 if (call.IsDocumentation()) | 2448 if (call.IsDocumentation()) |
2468 { | 2449 { |
2469 std::string r = GetResourceTypeText(t, false /* plural */, false /* upper case */); | 2450 std::string r = GetResourceTypeText(level, false /* plural */, false /* upper case */); |
2470 AddAttachmentDocumentation(call, r); | 2451 AddAttachmentDocumentation(call, r); |
2471 call.GetDocumentation() | 2452 call.GetDocumentation() |
2472 .SetTag(GetResourceTypeText(t, true /* plural */, true /* upper case */)) | 2453 .SetTag(GetResourceTypeText(level, true /* plural */, true /* upper case */)) |
2473 .SetSummary("Get MD5 of attachment on disk") | 2454 .SetSummary("Get MD5 of attachment on disk") |
2474 .SetDescription("Get the MD5 hash of one attachment associated with the given " + r + ", as stored on the disk. " | 2455 .SetDescription("Get the MD5 hash of one attachment associated with the given " + r + ", as stored on the disk. " |
2475 "This is different from `.../md5` iff `EnableStorage` is `true`.") | 2456 "This is different from `.../md5` iff `EnableStorage` is `true`.") |
2476 .AddAnswerType(MimeType_PlainText, "The MD5 of the attachment, as stored on the disk"); | 2457 .AddAnswerType(MimeType_PlainText, "The MD5 of the attachment, as stored on the disk"); |
2477 return; | 2458 return; |
2478 } | 2459 } |
2479 | 2460 |
2480 FileInfo info; | 2461 FileInfo info; |
2481 if (GetAttachmentInfo(info, t, call) && | 2462 if (GetAttachmentInfo(info, level, call) && |
2482 info.GetCompressedMD5() != "") | 2463 info.GetCompressedMD5() != "") |
2483 { | 2464 { |
2484 call.GetOutput().AnswerBuffer(boost::lexical_cast<std::string>(info.GetCompressedMD5()), MimeType_PlainText); | 2465 call.GetOutput().AnswerBuffer(boost::lexical_cast<std::string>(info.GetCompressedMD5()), MimeType_PlainText); |
2485 } | 2466 } |
2486 } | 2467 } |
2487 | 2468 |
2488 | 2469 |
2489 static void VerifyAttachment(RestApiPostCall& call) | 2470 static void VerifyAttachment(RestApiPostCall& call) |
2490 { | 2471 { |
2491 const ResourceType t = GetResourceTypeFromUri(call); | 2472 const ResourceType level = GetResourceTypeFromUri(call); |
2492 | 2473 |
2493 if (call.IsDocumentation()) | 2474 if (call.IsDocumentation()) |
2494 { | 2475 { |
2495 std::string r = GetResourceTypeText(t, false /* plural */, false /* upper case */); | 2476 std::string r = GetResourceTypeText(level, false /* plural */, false /* upper case */); |
2496 call.GetDocumentation() | 2477 call.GetDocumentation() |
2497 .SetTag(GetResourceTypeText(t, true /* plural */, true /* upper case */)) | 2478 .SetTag(GetResourceTypeText(level, true /* plural */, true /* upper case */)) |
2498 .SetSummary("Verify attachment") | 2479 .SetSummary("Verify attachment") |
2499 .SetDescription("Verify that the attachment is not corrupted, by validating its MD5 hash") | 2480 .SetDescription("Verify that the attachment is not corrupted, by validating its MD5 hash") |
2500 .SetUriArgument("id", "Orthanc identifier of the " + r + " of interest") | 2481 .SetUriArgument("id", "Orthanc identifier of the " + r + " of interest") |
2501 .SetUriArgument("name", "The name of the attachment, or its index (cf. `UserContentType` configuration option)") | 2482 .SetUriArgument("name", "The name of the attachment, or its index (cf. `UserContentType` configuration option)") |
2502 .AddAnswerType(MimeType_Json, "On success, a valid JSON object is returned"); | 2483 .AddAnswerType(MimeType_Json, "On success, a valid JSON object is returned"); |
2503 return; | 2484 return; |
2504 } | 2485 } |
2505 | 2486 |
2506 ServerContext& context = OrthancRestApi::GetContext(call); | 2487 ServerContext& context = OrthancRestApi::GetContext(call); |
2507 CheckValidResourceType(call); | |
2508 | 2488 |
2509 std::string publicId = call.GetUriComponent("id", ""); | 2489 std::string publicId = call.GetUriComponent("id", ""); |
2510 std::string name = call.GetUriComponent("name", ""); | 2490 std::string name = call.GetUriComponent("name", ""); |
2511 FileContentType contentType = StringToContentType(name); | 2491 FileContentType contentType = StringToContentType(name); |
2512 | 2492 |
2513 FileInfo info; | 2493 FileInfo info; |
2514 int64_t revision; // Ignored | 2494 int64_t revision; // Ignored |
2515 if (!OrthancRestApi::GetIndex(call).LookupAttachment(info, revision, t, publicId, contentType) || | 2495 if (!OrthancRestApi::GetIndex(call).LookupAttachment(info, revision, level, publicId, contentType) || |
2516 info.GetCompressedMD5() == "" || | 2496 info.GetCompressedMD5() == "" || |
2517 info.GetUncompressedMD5() == "") | 2497 info.GetUncompressedMD5() == "") |
2518 { | 2498 { |
2519 // Inexistent resource, or no MD5 available | 2499 // Inexistent resource, or no MD5 available |
2520 return; | 2500 return; |
2524 | 2504 |
2525 // First check whether the compressed data is correctly stored in the disk | 2505 // First check whether the compressed data is correctly stored in the disk |
2526 std::string data; | 2506 std::string data; |
2527 std::string attachmentId; | 2507 std::string attachmentId; |
2528 | 2508 |
2529 context.ReadAttachment(data, revision, attachmentId, t, publicId, StringToContentType(name), false, true /* skipCache when you absolutely need the compressed data */); | 2509 context.ReadAttachment(data, revision, attachmentId, level, publicId, StringToContentType(name), false, true /* skipCache when you absolutely need the compressed data */); |
2530 | 2510 |
2531 std::string actualMD5; | 2511 std::string actualMD5; |
2532 Toolbox::ComputeMD5(actualMD5, data); | 2512 Toolbox::ComputeMD5(actualMD5, data); |
2533 | 2513 |
2534 if (actualMD5 == info.GetCompressedMD5()) | 2514 if (actualMD5 == info.GetCompressedMD5()) |
2539 { | 2519 { |
2540 ok = true; | 2520 ok = true; |
2541 } | 2521 } |
2542 else | 2522 else |
2543 { | 2523 { |
2544 context.ReadAttachment(data, revision, attachmentId, t, publicId, StringToContentType(name), true, true /* skipCache when you absolutely need the compressed data */); | 2524 context.ReadAttachment(data, revision, attachmentId, level, publicId, StringToContentType(name), true, true /* skipCache when you absolutely need the compressed data */); |
2545 Toolbox::ComputeMD5(actualMD5, data); | 2525 Toolbox::ComputeMD5(actualMD5, data); |
2546 ok = (actualMD5 == info.GetUncompressedMD5()); | 2526 ok = (actualMD5 == info.GetUncompressedMD5()); |
2547 } | 2527 } |
2548 } | 2528 } |
2549 | 2529 |
2559 } | 2539 } |
2560 | 2540 |
2561 | 2541 |
2562 static void UploadAttachment(RestApiPutCall& call) | 2542 static void UploadAttachment(RestApiPutCall& call) |
2563 { | 2543 { |
2564 if (call.IsDocumentation()) | 2544 const ResourceType level = GetResourceTypeFromUri(call); |
2565 { | 2545 |
2566 ResourceType t = StringToResourceType(call.GetFullUri()[0].c_str()); | 2546 if (call.IsDocumentation()) |
2567 std::string r = GetResourceTypeText(t, false /* plural */, false /* upper case */); | 2547 { |
2568 call.GetDocumentation() | 2548 std::string r = GetResourceTypeText(level, false /* plural */, false /* upper case */); |
2569 .SetTag(GetResourceTypeText(t, true /* plural */, true /* upper case */)) | 2549 call.GetDocumentation() |
2550 .SetTag(GetResourceTypeText(level, true /* plural */, true /* upper case */)) | |
2570 .SetSummary("Set attachment") | 2551 .SetSummary("Set attachment") |
2571 .SetDescription("Attach a file to the given DICOM " + r + | 2552 .SetDescription("Attach a file to the given DICOM " + r + |
2572 ". This call will fail if trying to modify a system attachment (i.e. whose index is < 1024).") | 2553 ". This call will fail if trying to modify a system attachment (i.e. whose index is < 1024).") |
2573 .SetUriArgument("id", "Orthanc identifier of the " + r + " of interest") | 2554 .SetUriArgument("id", "Orthanc identifier of the " + r + " of interest") |
2574 .SetUriArgument("name", "The name of the attachment, or its index (cf. `UserContentType` configuration option)") | 2555 .SetUriArgument("name", "The name of the attachment, or its index (cf. `UserContentType` configuration option)") |
2577 .SetHttpHeader("If-Match", "Revision of the attachment, if this is not the first time this attachment is set."); | 2558 .SetHttpHeader("If-Match", "Revision of the attachment, if this is not the first time this attachment is set."); |
2578 return; | 2559 return; |
2579 } | 2560 } |
2580 | 2561 |
2581 ServerContext& context = OrthancRestApi::GetContext(call); | 2562 ServerContext& context = OrthancRestApi::GetContext(call); |
2582 CheckValidResourceType(call); | |
2583 | 2563 |
2584 std::string publicId = call.GetUriComponent("id", ""); | 2564 std::string publicId = call.GetUriComponent("id", ""); |
2585 std::string name = call.GetUriComponent("name", ""); | 2565 std::string name = call.GetUriComponent("name", ""); |
2586 | 2566 |
2587 FileContentType contentType = StringToContentType(name); | 2567 FileContentType contentType = StringToContentType(name); |
2620 } | 2600 } |
2621 | 2601 |
2622 | 2602 |
2623 static void DeleteAttachment(RestApiDeleteCall& call) | 2603 static void DeleteAttachment(RestApiDeleteCall& call) |
2624 { | 2604 { |
2625 if (call.IsDocumentation()) | 2605 const ResourceType level = GetResourceTypeFromUri(call); |
2626 { | 2606 |
2627 ResourceType t = StringToResourceType(call.GetFullUri()[0].c_str()); | 2607 if (call.IsDocumentation()) |
2628 std::string r = GetResourceTypeText(t, false /* plural */, false /* upper case */); | 2608 { |
2629 call.GetDocumentation() | 2609 std::string r = GetResourceTypeText(level, false /* plural */, false /* upper case */); |
2630 .SetTag(GetResourceTypeText(t, true /* plural */, true /* upper case */)) | 2610 call.GetDocumentation() |
2611 .SetTag(GetResourceTypeText(level, true /* plural */, true /* upper case */)) | |
2631 .SetSummary("Delete attachment") | 2612 .SetSummary("Delete attachment") |
2632 .SetDescription("Delete an attachment associated with the given DICOM " + r + | 2613 .SetDescription("Delete an attachment associated with the given DICOM " + r + |
2633 ". This call will fail if trying to delete a system attachment (i.e. whose index is < 1024).") | 2614 ". This call will fail if trying to delete a system attachment (i.e. whose index is < 1024).") |
2634 .SetUriArgument("id", "Orthanc identifier of the " + r + " of interest") | 2615 .SetUriArgument("id", "Orthanc identifier of the " + r + " of interest") |
2635 .SetUriArgument("name", "The name of the attachment, or its index (cf. `UserContentType` configuration option)") | 2616 .SetUriArgument("name", "The name of the attachment, or its index (cf. `UserContentType` configuration option)") |
2636 .SetHttpHeader("If-Match", "Revision of the attachment, to check if its content has not changed and can " | 2617 .SetHttpHeader("If-Match", "Revision of the attachment, to check if its content has not changed and can " |
2637 "be deleted. This header is mandatory if `CheckRevisions` option is `true`."); | 2618 "be deleted. This header is mandatory if `CheckRevisions` option is `true`."); |
2638 return; | 2619 return; |
2639 } | 2620 } |
2640 | 2621 |
2641 CheckValidResourceType(call); | |
2642 | |
2643 std::string publicId = call.GetUriComponent("id", ""); | 2622 std::string publicId = call.GetUriComponent("id", ""); |
2644 std::string name = call.GetUriComponent("name", ""); | 2623 std::string name = call.GetUriComponent("name", ""); |
2645 FileContentType contentType = StringToContentType(name); | 2624 FileContentType contentType = StringToContentType(name); |
2646 | 2625 |
2647 bool allowed; | 2626 bool allowed; |
2709 | 2688 |
2710 | 2689 |
2711 template <enum CompressionType compression> | 2690 template <enum CompressionType compression> |
2712 static void ChangeAttachmentCompression(RestApiPostCall& call) | 2691 static void ChangeAttachmentCompression(RestApiPostCall& call) |
2713 { | 2692 { |
2714 const ResourceType t = GetResourceTypeFromUri(call); | 2693 const ResourceType level = GetResourceTypeFromUri(call); |
2715 | 2694 |
2716 if (call.IsDocumentation()) | 2695 if (call.IsDocumentation()) |
2717 { | 2696 { |
2718 std::string r = GetResourceTypeText(t, false /* plural */, false /* upper case */); | 2697 std::string r = GetResourceTypeText(level, false /* plural */, false /* upper case */); |
2719 call.GetDocumentation() | 2698 call.GetDocumentation() |
2720 .SetTag(GetResourceTypeText(t, true /* plural */, true /* upper case */)) | 2699 .SetTag(GetResourceTypeText(level, true /* plural */, true /* upper case */)) |
2721 .SetSummary(compression == CompressionType_None ? "Uncompress attachment" : "Compress attachment") | 2700 .SetSummary(compression == CompressionType_None ? "Uncompress attachment" : "Compress attachment") |
2722 .SetDescription("Change the compression scheme that is used to store an attachment.") | 2701 .SetDescription("Change the compression scheme that is used to store an attachment.") |
2723 .SetUriArgument("id", "Orthanc identifier of the " + r + " of interest") | 2702 .SetUriArgument("id", "Orthanc identifier of the " + r + " of interest") |
2724 .SetUriArgument("name", "The name of the attachment, or its index (cf. `UserContentType` configuration option)"); | 2703 .SetUriArgument("name", "The name of the attachment, or its index (cf. `UserContentType` configuration option)"); |
2725 return; | 2704 return; |
2726 } | 2705 } |
2727 | 2706 |
2728 CheckValidResourceType(call); | |
2729 | |
2730 std::string publicId = call.GetUriComponent("id", ""); | 2707 std::string publicId = call.GetUriComponent("id", ""); |
2731 std::string name = call.GetUriComponent("name", ""); | 2708 std::string name = call.GetUriComponent("name", ""); |
2732 FileContentType contentType = StringToContentType(name); | 2709 FileContentType contentType = StringToContentType(name); |
2733 | 2710 |
2734 OrthancRestApi::GetContext(call).ChangeAttachmentCompression(t, publicId, contentType, compression); | 2711 OrthancRestApi::GetContext(call).ChangeAttachmentCompression(level, publicId, contentType, compression); |
2735 call.GetOutput().AnswerBuffer("{}", MimeType_Json); | 2712 call.GetOutput().AnswerBuffer("{}", MimeType_Json); |
2736 } | 2713 } |
2737 | 2714 |
2738 | 2715 |
2739 static void IsAttachmentCompressed(RestApiGetCall& call) | 2716 static void IsAttachmentCompressed(RestApiGetCall& call) |
2740 { | 2717 { |
2741 const ResourceType t = GetResourceTypeFromUri(call); | 2718 const ResourceType level = GetResourceTypeFromUri(call); |
2742 | 2719 |
2743 if (call.IsDocumentation()) | 2720 if (call.IsDocumentation()) |
2744 { | 2721 { |
2745 std::string r = GetResourceTypeText(t, false /* plural */, false /* upper case */); | 2722 std::string r = GetResourceTypeText(level, false /* plural */, false /* upper case */); |
2746 AddAttachmentDocumentation(call, r); | 2723 AddAttachmentDocumentation(call, r); |
2747 call.GetDocumentation() | 2724 call.GetDocumentation() |
2748 .SetTag(GetResourceTypeText(t, true /* plural */, true /* upper case */)) | 2725 .SetTag(GetResourceTypeText(level, true /* plural */, true /* upper case */)) |
2749 .SetSummary("Is attachment compressed?") | 2726 .SetSummary("Is attachment compressed?") |
2750 .SetDescription("Test whether the attachment has been stored as a compressed file on the disk.") | 2727 .SetDescription("Test whether the attachment has been stored as a compressed file on the disk.") |
2751 .AddAnswerType(MimeType_PlainText, "`0` if the attachment was stored uncompressed, `1` if it was compressed"); | 2728 .AddAnswerType(MimeType_PlainText, "`0` if the attachment was stored uncompressed, `1` if it was compressed"); |
2752 return; | 2729 return; |
2753 } | 2730 } |
2754 | 2731 |
2755 FileInfo info; | 2732 FileInfo info; |
2756 if (GetAttachmentInfo(info, t, call)) | 2733 if (GetAttachmentInfo(info, level, call)) |
2757 { | 2734 { |
2758 std::string answer = (info.GetCompressionType() == CompressionType_None) ? "0" : "1"; | 2735 std::string answer = (info.GetCompressionType() == CompressionType_None) ? "0" : "1"; |
2759 call.GetOutput().AnswerBuffer(answer, MimeType_PlainText); | 2736 call.GetOutput().AnswerBuffer(answer, MimeType_PlainText); |
2760 } | 2737 } |
2761 } | 2738 } |
2864 } | 2841 } |
2865 | 2842 |
2866 | 2843 |
2867 static void GetSharedTags(RestApiGetCall& call) | 2844 static void GetSharedTags(RestApiGetCall& call) |
2868 { | 2845 { |
2846 const ResourceType level = GetResourceTypeFromUri(call); | |
2847 | |
2869 if (call.IsDocumentation()) | 2848 if (call.IsDocumentation()) |
2870 { | 2849 { |
2871 OrthancRestApi::DocumentDicomFormat(call, DicomToJsonFormat_Full); | 2850 OrthancRestApi::DocumentDicomFormat(call, DicomToJsonFormat_Full); |
2872 | 2851 |
2873 ResourceType t = StringToResourceType(call.GetFullUri()[0].c_str()); | 2852 std::string r = GetResourceTypeText(level, false /* plural */, false /* upper case */); |
2874 std::string r = GetResourceTypeText(t, false /* plural */, false /* upper case */); | 2853 call.GetDocumentation() |
2875 call.GetDocumentation() | 2854 .SetTag(GetResourceTypeText(level, true /* plural */, true /* upper case */)) |
2876 .SetTag(GetResourceTypeText(t, true /* plural */, true /* upper case */)) | |
2877 .SetSummary("Get shared tags") | 2855 .SetSummary("Get shared tags") |
2878 .SetDescription("Extract the DICOM tags whose value is constant across all the child instances of " | 2856 .SetDescription("Extract the DICOM tags whose value is constant across all the child instances of " |
2879 "the DICOM " + r + " whose Orthanc identifier is provided in the URL") | 2857 "the DICOM " + r + " whose Orthanc identifier is provided in the URL") |
2880 .SetUriArgument("id", "Orthanc identifier of the " + r + " of interest") | 2858 .SetUriArgument("id", "Orthanc identifier of the " + r + " of interest") |
2881 .AddAnswerType(MimeType_Json, "JSON object containing the values of the DICOM tags") | 2859 .AddAnswerType(MimeType_Json, "JSON object containing the values of the DICOM tags") |
2882 .SetTruncatedJsonHttpGetSample(GetDocumentationSampleResource(t) + "/shared-tags", 5); | 2860 .SetTruncatedJsonHttpGetSample(GetDocumentationSampleResource(level) + "/shared-tags", 5); |
2883 return; | 2861 return; |
2884 } | 2862 } |
2885 | 2863 |
2886 ServerContext& context = OrthancRestApi::GetContext(call); | 2864 ServerContext& context = OrthancRestApi::GetContext(call); |
2887 std::string publicId = call.GetUriComponent("id", ""); | 2865 std::string publicId = call.GetUriComponent("id", ""); |
3574 } | 3552 } |
3575 | 3553 |
3576 | 3554 |
3577 static void GetChildInstancesTags(RestApiGetCall& call) | 3555 static void GetChildInstancesTags(RestApiGetCall& call) |
3578 { | 3556 { |
3557 const ResourceType level = GetResourceTypeFromUri(call); | |
3558 | |
3579 if (call.IsDocumentation()) | 3559 if (call.IsDocumentation()) |
3580 { | 3560 { |
3581 OrthancRestApi::DocumentDicomFormat(call, DicomToJsonFormat_Full); | 3561 OrthancRestApi::DocumentDicomFormat(call, DicomToJsonFormat_Full); |
3582 | 3562 |
3583 ResourceType t = StringToResourceType(call.GetFullUri()[0].c_str()); | 3563 std::string r = GetResourceTypeText(level, false /* plural */, false /* upper case */); |
3584 std::string r = GetResourceTypeText(t, false /* plural */, false /* upper case */); | 3564 call.GetDocumentation() |
3585 call.GetDocumentation() | 3565 .SetTag(GetResourceTypeText(level, true /* plural */, true /* upper case */)) |
3586 .SetTag(GetResourceTypeText(t, true /* plural */, true /* upper case */)) | |
3587 .SetSummary("Get tags of instances") | 3566 .SetSummary("Get tags of instances") |
3588 .SetDescription("Get the tags of all the child instances of the DICOM " + r + | 3567 .SetDescription("Get the tags of all the child instances of the DICOM " + r + |
3589 " whose Orthanc identifier is provided in the URL") | 3568 " whose Orthanc identifier is provided in the URL") |
3590 .SetUriArgument("id", "Orthanc identifier of the " + r + " of interest") | 3569 .SetUriArgument("id", "Orthanc identifier of the " + r + " of interest") |
3591 .SetHttpGetArgument(IGNORE_LENGTH, RestApiCallDocumentation::Type_JsonListOfStrings, | 3570 .SetHttpGetArgument(IGNORE_LENGTH, RestApiCallDocumentation::Type_JsonListOfStrings, |
3592 "Also include the DICOM tags that are provided in this list, even if their associated value is long", false) | 3571 "Also include the DICOM tags that are provided in this list, even if their associated value is long", false) |
3593 .AddAnswerType(MimeType_Json, "JSON object associating the Orthanc identifiers of the instances, with the values of their DICOM tags") | 3572 .AddAnswerType(MimeType_Json, "JSON object associating the Orthanc identifiers of the instances, with the values of their DICOM tags") |
3594 .SetTruncatedJsonHttpGetSample(GetDocumentationSampleResource(t) + "/instances-tags", 5); | 3573 .SetTruncatedJsonHttpGetSample(GetDocumentationSampleResource(level) + "/instances-tags", 5); |
3595 return; | 3574 return; |
3596 } | 3575 } |
3597 | 3576 |
3598 ServerContext& context = OrthancRestApi::GetContext(call); | 3577 ServerContext& context = OrthancRestApi::GetContext(call); |
3599 std::string publicId = call.GetUriComponent("id", ""); | 3578 std::string publicId = call.GetUriComponent("id", ""); |