From 5a3291bb70b91ea1afd79d7fd02638c5331af5bf Mon Sep 17 00:00:00 2001 From: Philip Durbin Date: Fri, 22 Nov 2024 13:26:38 -0500 Subject: [PATCH 1/6] expose links to all export formats via Signposting #10542 --- doc/release-notes/10542-signposting.md | 9 ++++ .../source/admin/discoverability.rst | 2 +- doc/sphinx-guides/source/api/native-api.rst | 14 ++++-- .../source/user/dataset-management.rst | 2 + .../export/SchemaDotOrgExporter.java | 6 ++- .../dataverse/util/SignpostingResources.java | 45 ++++++++++++++----- .../iq/dataverse/api/SignpostingIT.java | 22 +++++++++ 7 files changed, 84 insertions(+), 16 deletions(-) create mode 100644 doc/release-notes/10542-signposting.md diff --git a/doc/release-notes/10542-signposting.md b/doc/release-notes/10542-signposting.md new file mode 100644 index 00000000000..b6429310323 --- /dev/null +++ b/doc/release-notes/10542-signposting.md @@ -0,0 +1,9 @@ +# Signposting Output Now Contains Links to All Dataset Metadata Export Formats + +When Signposting was added in Dataverse 5.14 (#8981), it only provided links for the `schema.org` metadata export format. + +The output of HEAD, GET, and the Signposting "linkset" API have all been updated to include links to all available dataset metadata export formats (including any external exporters, such as Croissant, that have been enabled). + +This provides a lightweight machine-readable way to first retrieve a list of links (via a HTTP HEAD request, for example) to each available metadata export format and then follow up with a request for the export format of interest. + +See also [the docs](https://preview.guides.gdcc.io/en/develop/api/native-api.html#retrieve-signposting-information) and #10542. diff --git a/doc/sphinx-guides/source/admin/discoverability.rst b/doc/sphinx-guides/source/admin/discoverability.rst index 19ef7250a29..22ff66246f0 100644 --- a/doc/sphinx-guides/source/admin/discoverability.rst +++ b/doc/sphinx-guides/source/admin/discoverability.rst @@ -51,7 +51,7 @@ The Dataverse team has been working with Google on both formats. Google has `ind Signposting +++++++++++ -The Dataverse software supports `Signposting `_. This allows machines to request more information about a dataset through the `Link `_ HTTP header. +The Dataverse software supports `Signposting `_. This allows machines to request more information about a dataset through the `Link `_ HTTP header. Links to all enabled metadata export formats are given. See :ref:`metadata-export-formats` for a list. There are 2 Signposting profile levels, level 1 and level 2. In this implementation, * Level 1 links are shown `as recommended `_ in the "Link" diff --git a/doc/sphinx-guides/source/api/native-api.rst b/doc/sphinx-guides/source/api/native-api.rst index 2bf0cd5c635..2bb27677b9b 100644 --- a/doc/sphinx-guides/source/api/native-api.rst +++ b/doc/sphinx-guides/source/api/native-api.rst @@ -1352,9 +1352,16 @@ The fully expanded example above (without environment variables) looks like this curl "https://demo.dataverse.org/api/datasets/export?exporter=ddi&persistentId=doi:10.5072/FK2/J8SJZB" -.. note:: Supported exporters (export formats) are ``ddi``, ``oai_ddi``, ``dcterms``, ``oai_dc``, ``schema.org`` , ``OAI_ORE`` , ``Datacite``, ``oai_datacite`` and ``dataverse_json``. Descriptive names can be found under :ref:`metadata-export-formats` in the User Guide. +Available Dataset Metadata Exporters +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Dataset metadata exporters that ship with Dataverse are ``ddi``, ``oai_ddi``, ``dcterms``, ``oai_dc``, ``schema.org`` , ``OAI_ORE`` , ``Datacite``, ``oai_datacite`` and ``dataverse_json``. These are the strings to pass as ``$METADATA_FORMAT`` in the examples above. Descriptive names for each format can be found under :ref:`metadata-export-formats` in the User Guide. + +Additional exporters can be enabled, as described under :ref:`external-exporters` in the Installation Guide. They are listed under :ref:`inventory-of-external-exporters`. + +To discover the machine-readable name of exporters (e.g. ``ddi``) that have been enabled on the installation of Dataverse you are using, you can use the Signposting "linkset" API documented under :ref:`signposting-api`. -.. note:: Additional exporters can be enabled, as described under :ref:`external-exporters` in the Installation Guide. To discover the machine-readable name of each exporter (e.g. ``ddi``), check :ref:`inventory-of-external-exporters` or ``getFormatName`` in the exporter's source code. +To discover the machine-readable name of exporters generally, check :ref:`inventory-of-external-exporters` or ``getFormatName`` in the exporter's source code. Schema.org JSON-LD ^^^^^^^^^^^^^^^^^^ @@ -1368,6 +1375,7 @@ Both forms are valid according to Google's Structured Data Testing Tool at https The standard has further evolved into a format called Croissant. For details, see :ref:`schema.org-head` in the Admin Guide. +The ``schema.org`` format changed after Dataverse 6.4 as well. Previously its content type was "application/json" but now it is "application/ld+json". List Files in a Dataset ~~~~~~~~~~~~~~~~~~~~~~~ @@ -2936,7 +2944,7 @@ Signposting involves the addition of a `Link ;rel="cite-as", ;rel="describedby";type="application/vnd.citationstyles.csl+json",;rel="describedby";type="application/ld+json", ;rel="type",;rel="type", ;rel="license", ; rel="linkset";type="application/linkset+json"`` +``Link: ;rel="cite-as", ;rel="describedby";type="application/vnd.citationstyles.csl+json",;rel="describedby";type="application/json",;rel="describedby";type="application/xml",;rel="describedby";type="application/xml",;rel="describedby";type="application/xml",;rel="describedby";type="application/ld+json",;rel="describedby";type="application/xml",;rel="describedby";type="application/xml",;rel="describedby";type="text/html",;rel="describedby";type="application/json",;rel="describedby";type="application/xml", ;rel="type",;rel="type", ;rel="license", ; rel="linkset";type="application/linkset+json"`` The URL for linkset information is discoverable under the ``rel="linkset";type="application/linkset+json`` entry in the "Link" header, such as in the example above. diff --git a/doc/sphinx-guides/source/user/dataset-management.rst b/doc/sphinx-guides/source/user/dataset-management.rst index b3a14554b40..d1acb3294fc 100755 --- a/doc/sphinx-guides/source/user/dataset-management.rst +++ b/doc/sphinx-guides/source/user/dataset-management.rst @@ -43,6 +43,8 @@ Additional formats can be enabled. See :ref:`inventory-of-external-exporters` in Each of these metadata exports contains the metadata of the most recently published version of the dataset. +For each dataset, links to each enabled metadata format are available programmatically via Signposting. For details, see :ref:`discovery-sign-posting` in the Admin Guide and :ref:`signposting-api` in the API Guide. + .. _adding-new-dataset: Adding a New Dataset diff --git a/src/main/java/edu/harvard/iq/dataverse/export/SchemaDotOrgExporter.java b/src/main/java/edu/harvard/iq/dataverse/export/SchemaDotOrgExporter.java index 0c4b39fd641..d4f2f95389f 100644 --- a/src/main/java/edu/harvard/iq/dataverse/export/SchemaDotOrgExporter.java +++ b/src/main/java/edu/harvard/iq/dataverse/export/SchemaDotOrgExporter.java @@ -111,7 +111,11 @@ public Boolean isAvailableToUsers() { @Override public String getMediaType() { - return MediaType.APPLICATION_JSON; + /** + * Changed from "application/json" to "application/ld+json" because + * that's what Signposting expects. + */ + return "application/ld+json"; } } diff --git a/src/main/java/edu/harvard/iq/dataverse/util/SignpostingResources.java b/src/main/java/edu/harvard/iq/dataverse/util/SignpostingResources.java index b6f8870aa2d..d4e6ba2b39d 100644 --- a/src/main/java/edu/harvard/iq/dataverse/util/SignpostingResources.java +++ b/src/main/java/edu/harvard/iq/dataverse/util/SignpostingResources.java @@ -16,6 +16,7 @@ Two configurable options allow changing the limit for the number of authors or d import edu.harvard.iq.dataverse.*; import edu.harvard.iq.dataverse.dataset.DatasetUtil; +import edu.harvard.iq.dataverse.export.ExportService; import jakarta.json.Json; import jakarta.json.JsonArrayBuilder; import jakarta.json.JsonObjectBuilder; @@ -28,6 +29,8 @@ Two configurable options allow changing the limit for the number of authors or d import java.util.logging.Logger; import static edu.harvard.iq.dataverse.util.json.NullSafeJsonBuilder.jsonObjectBuilder; +import io.gdcc.spi.export.ExportException; +import io.gdcc.spi.export.Exporter; public class SignpostingResources { private static final Logger logger = Logger.getLogger(SignpostingResources.class.getCanonicalName()); @@ -72,8 +75,18 @@ public String getLinks() { } String describedby = "<" + ds.getGlobalId().asURL().toString() + ">;rel=\"describedby\"" + ";type=\"" + "application/vnd.citationstyles.csl+json\""; - describedby += ",<" + systemConfig.getDataverseSiteUrl() + "/api/datasets/export?exporter=schema.org&persistentId=" - + ds.getProtocol() + ":" + ds.getAuthority() + "/" + ds.getIdentifier() + ">;rel=\"describedby\"" + ";type=\"application/ld+json\""; + ExportService instance = ExportService.getInstance(); + for (String[] labels : instance.getExportersLabels()) { + String formatName = labels[1]; + Exporter exporter; + try { + exporter = ExportService.getInstance().getExporter(formatName); + describedby += ",<" + systemConfig.getDataverseSiteUrl() + "/api/datasets/export?exporter=" + formatName + "&persistentId=" + + ds.getProtocol() + ":" + ds.getAuthority() + "/" + ds.getIdentifier() + ">;rel=\"describedby\"" + ";type=\"" + exporter.getMediaType() + "\""; + } catch (ExportException ex) { + logger.warning("Could not look up exporter based on " + formatName + ". Exception: " + ex); + } + } valueList.add(describedby); String type = ";rel=\"type\""; @@ -112,15 +125,25 @@ public JsonArrayBuilder getJsonLinkset() { ) ); - mediaTypes.add( - jsonObjectBuilder().add( - "href", - systemConfig.getDataverseSiteUrl() + "/api/datasets/export?exporter=schema.org&persistentId=" + ds.getProtocol() + ":" + ds.getAuthority() + "/" + ds.getIdentifier() - ).add( - "type", - "application/ld+json" - ) - ); + ExportService instance = ExportService.getInstance(); + for (String[] labels : instance.getExportersLabels()) { + String formatName = labels[1]; + Exporter exporter; + try { + exporter = ExportService.getInstance().getExporter(formatName); + mediaTypes.add( + jsonObjectBuilder().add( + "href", + systemConfig.getDataverseSiteUrl() + "/api/datasets/export?exporter=" + formatName + "&persistentId=" + ds.getProtocol() + ":" + ds.getAuthority() + "/" + ds.getIdentifier() + ).add( + "type", + exporter.getMediaType() + ) + ); + } catch (ExportException ex) { + logger.warning("Could not look up exporter based on " + formatName + ". Exception: " + ex); + } + } JsonArrayBuilder linksetJsonObj = Json.createArrayBuilder(); JsonObjectBuilder mandatory; diff --git a/src/test/java/edu/harvard/iq/dataverse/api/SignpostingIT.java b/src/test/java/edu/harvard/iq/dataverse/api/SignpostingIT.java index 75f514f3398..4327aa26778 100644 --- a/src/test/java/edu/harvard/iq/dataverse/api/SignpostingIT.java +++ b/src/test/java/edu/harvard/iq/dataverse/api/SignpostingIT.java @@ -58,6 +58,16 @@ public void testSignposting() { Response getHtml = given().get(datasetLandingPage); System.out.println("Link header: " + getHtml.getHeader("Link")); + if (false) { + // Split on commas to make the output more readable. + System.out.println("---"); + String header = getHtml.getHeader("Link"); + for (String string : header.split(",")) { + System.out.println(string + ","); + } + System.out.println("returning early..."); + return; + } getHtml.then().assertThat().statusCode(OK.getStatusCode()); @@ -67,6 +77,8 @@ public void testSignposting() { assertTrue(linkHeader.contains(datasetPid)); assertTrue(linkHeader.contains("cite-as")); assertTrue(linkHeader.contains("describedby")); + // Make sure we get more exporters besides just "schema.org". + assertTrue(linkHeader.contains("oai_datacite")); Response headHtml = given().head(datasetLandingPage); @@ -76,6 +88,7 @@ public void testSignposting() { // Make sure there's Signposting stuff in the "Link" header such as // the dataset PID, cite-as, etc. + // TODO: The comment above is a repeat and so are some of the assertions below. Consolidate? linkHeader = getHtml.getHeader("Link"); assertTrue(linkHeader.contains(datasetPid)); assertTrue(linkHeader.contains("cite-as")); @@ -90,8 +103,10 @@ public void testSignposting() { System.out.println("Linkset URL: " + linksetUrl); Response linksetResponse = given().accept(ContentType.JSON).get(linksetUrl); + linksetResponse.prettyPrint(); String responseString = linksetResponse.getBody().asString(); + System.out.println("response string: " + responseString); JsonObject data = JsonUtil.getJsonObject(responseString); JsonObject lso = data.getJsonArray("linkset").getJsonObject(0); @@ -107,6 +122,13 @@ public void testSignposting() { Pattern exporterPattern = Pattern.compile("[<\\[][^()\\[\\]]*?exporter=schema.org[^()\\[\\]]*[>\\]]"); Matcher exporterMatcher = exporterPattern.matcher(linkHeader); exporterMatcher.find(); + // TODO: make an assertion + //assertTrue(exporterMatcher.find()); + + // Test another + Pattern exporterPattern2 = Pattern.compile("exporter=oai_datacite"); + Matcher exporterMatcher2 = exporterPattern2.matcher(linkHeader); + assertTrue(exporterMatcher2.find()); Response exportDataset = UtilIT.exportDataset(datasetPid, "schema.org"); exportDataset.prettyPrint(); From 5a24a4ca9d58eaf22713929002922d98d3827b8e Mon Sep 17 00:00:00 2001 From: Philip Durbin Date: Fri, 22 Nov 2024 16:07:45 -0500 Subject: [PATCH 2/6] tweak exporter docs and cross link #10542 --- doc/sphinx-guides/source/api/native-api.rst | 44 ++++++++++++++++----- 1 file changed, 35 insertions(+), 9 deletions(-) diff --git a/doc/sphinx-guides/source/api/native-api.rst b/doc/sphinx-guides/source/api/native-api.rst index b915d0028c1..5ff527f4e39 100644 --- a/doc/sphinx-guides/source/api/native-api.rst +++ b/doc/sphinx-guides/source/api/native-api.rst @@ -1336,6 +1336,8 @@ Export Metadata of a Dataset in Various Formats |CORS| Export the metadata of the current published version of a dataset in various formats. +To get a list of available formats, see :ref:`available-exporters` and :ref:`get-export-formats`. + See also :ref:`batch-exports-through-the-api` and the note below: .. code-block:: bash @@ -1352,14 +1354,28 @@ The fully expanded example above (without environment variables) looks like this curl "https://demo.dataverse.org/api/datasets/export?exporter=ddi&persistentId=doi:10.5072/FK2/J8SJZB" +.. _available-exporters: + Available Dataset Metadata Exporters ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Dataset metadata exporters that ship with Dataverse are ``ddi``, ``oai_ddi``, ``dcterms``, ``oai_dc``, ``schema.org`` , ``OAI_ORE`` , ``Datacite``, ``oai_datacite`` and ``dataverse_json``. These are the strings to pass as ``$METADATA_FORMAT`` in the examples above. Descriptive names for each format can be found under :ref:`metadata-export-formats` in the User Guide. +The following dataset metadata exporters ship with Dataverse: + +- ``Datacite`` +- ``dataverse_json`` +- ``dcterms`` +- ``ddi`` +- ``oai_datacite`` +- ``oai_dc`` +- ``oai_ddi`` +- ``OAI_ORE`` +- ``schema.org`` -Additional exporters can be enabled, as described under :ref:`external-exporters` in the Installation Guide. They are listed under :ref:`inventory-of-external-exporters`. +These are the strings to pass as ``$METADATA_FORMAT`` in the examples above. Descriptive names for each format can be found under :ref:`metadata-export-formats` in the User Guide. -To discover the machine-readable name of exporters (e.g. ``ddi``) that have been enabled on the installation of Dataverse you are using, you can use the Signposting "linkset" API documented under :ref:`signposting-api`. +Additional exporters can be enabled, as described under :ref:`external-exporters` in the Installation Guide. The machine-readable name/identifier for each external exporter can be found under :ref:`inventory-of-external-exporters`. If you are interested in creating your own exporter, see :doc:`/developers/metadataexport`. + +To discover the machine-readable name of exporters (e.g. ``ddi``) that have been enabled on the installation of Dataverse you are using see :ref:`get-export-formats`. Alternatively, you can use the Signposting "linkset" API documented under :ref:`signposting-api`. To discover the machine-readable name of exporters generally, check :ref:`inventory-of-external-exporters` or ``getFormatName`` in the exporter's source code. @@ -2942,15 +2958,23 @@ Retrieve Signposting Information Dataverse supports :ref:`discovery-sign-posting` as a discovery mechanism. Signposting involves the addition of a `Link `__ HTTP header providing summary information on GET and HEAD requests to retrieve the dataset page and a separate /linkset API call to retrieve additional information. -Here is an example of a "Link" header: +Signposting Link HTTP Header +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Here is an example of a HTTP "Link" header from a GET or HEAD request for a dataset landing page: ``Link: ;rel="cite-as", ;rel="describedby";type="application/vnd.citationstyles.csl+json",;rel="describedby";type="application/json",;rel="describedby";type="application/xml",;rel="describedby";type="application/xml",;rel="describedby";type="application/xml",;rel="describedby";type="application/ld+json",;rel="describedby";type="application/xml",;rel="describedby";type="application/xml",;rel="describedby";type="text/html",;rel="describedby";type="application/json",;rel="describedby";type="application/xml", ;rel="type",;rel="type", ;rel="license", ; rel="linkset";type="application/linkset+json"`` -The URL for linkset information is discoverable under the ``rel="linkset";type="application/linkset+json`` entry in the "Link" header, such as in the example above. +The URL for linkset information (described below) is discoverable under the ``rel="linkset";type="application/linkset+json`` entry in the "Link" header, such as in the example above. + +Signposting Linkset API Endpoint +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The reponse includes a JSON object conforming to the `Signposting `__ specification. As part of this conformance, unlike most Dataverse API responses, the output is not wrapped in a ``{"status":"OK","data":{`` object. Signposting is not supported for draft dataset versions. +Like :ref:`get-export-formats`, this API can be used to get URLs to dataset metadata export formats, but with URLs for the dataset in question. + .. code-block:: bash export SERVER_URL=https://demo.dataverse.org @@ -4889,12 +4913,14 @@ The fully expanded example above (without environment variables) looks like this curl "https://demo.dataverse.org/api/info/settings/:MaxEmbargoDurationInMonths" -Get Export Formats -~~~~~~~~~~~~~~~~~~~~~~~~~~~ +.. _get-export-formats: + +Get Dataset Metadata Export Formats +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Get the available export formats, including custom formats. +Get the available dataset metadata export formats, including formats from external exporters (see :ref:`available-exporters`). -The response contains an object with available format names as keys, and as values an object with the following properties: +The response contains a JSON object with the available format names as keys (these can be passed to :ref:`export-dataset-metadata-api`), and values as objects with the following properties: * ``displayName`` * ``mediaType`` From ca93d60685b9d4a0a3ea62e8ce8b0e2dc2203a19 Mon Sep 17 00:00:00 2001 From: Philip Durbin Date: Mon, 25 Nov 2024 09:52:38 -0500 Subject: [PATCH 3/6] remove hard-coded "/" and use GlobalID object instead, add tests #10542 --- .../iq/dataverse/util/SignpostingResources.java | 15 +++++++++------ .../harvard/iq/dataverse/api/SignpostingIT.java | 10 ++++++++++ 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/util/SignpostingResources.java b/src/main/java/edu/harvard/iq/dataverse/util/SignpostingResources.java index d4e6ba2b39d..8bebcf4d438 100644 --- a/src/main/java/edu/harvard/iq/dataverse/util/SignpostingResources.java +++ b/src/main/java/edu/harvard/iq/dataverse/util/SignpostingResources.java @@ -81,8 +81,7 @@ public String getLinks() { Exporter exporter; try { exporter = ExportService.getInstance().getExporter(formatName); - describedby += ",<" + systemConfig.getDataverseSiteUrl() + "/api/datasets/export?exporter=" + formatName + "&persistentId=" - + ds.getProtocol() + ":" + ds.getAuthority() + "/" + ds.getIdentifier() + ">;rel=\"describedby\"" + ";type=\"" + exporter.getMediaType() + "\""; + describedby += ",<" + getExporterUrl(formatName, ds) + ">;rel=\"describedby\"" + ";type=\"" + exporter.getMediaType() + "\""; } catch (ExportException ex) { logger.warning("Could not look up exporter based on " + formatName + ". Exception: " + ex); } @@ -98,7 +97,7 @@ public String getLinks() { String linkset = "<" + systemConfig.getDataverseSiteUrl() + "/api/datasets/:persistentId/versions/" + workingDatasetVersion.getVersionNumber() + "." + workingDatasetVersion.getMinorVersionNumber() - + "/linkset?persistentId=" + ds.getProtocol() + ":" + ds.getAuthority() + "/" + ds.getIdentifier() + "> ; rel=\"linkset\";type=\"application/linkset+json\""; + + "/linkset?persistentId=" + ds.getGlobalId().asString() + "> ; rel=\"linkset\";type=\"application/linkset+json\""; valueList.add(linkset); logger.fine(String.format("valueList is: %s", valueList)); @@ -108,7 +107,7 @@ public String getLinks() { public JsonArrayBuilder getJsonLinkset() { Dataset ds = workingDatasetVersion.getDataset(); GlobalId gid = ds.getGlobalId(); - String landingPage = systemConfig.getDataverseSiteUrl() + "/dataset.xhtml?persistentId=" + ds.getProtocol() + ":" + ds.getAuthority() + "/" + ds.getIdentifier(); + String landingPage = systemConfig.getDataverseSiteUrl() + "/dataset.xhtml?persistentId=" + ds.getGlobalId().asString(); JsonArrayBuilder authors = getJsonAuthors(getAuthorURLs(false)); JsonArrayBuilder items = getJsonItems(); @@ -133,8 +132,7 @@ public JsonArrayBuilder getJsonLinkset() { exporter = ExportService.getInstance().getExporter(formatName); mediaTypes.add( jsonObjectBuilder().add( - "href", - systemConfig.getDataverseSiteUrl() + "/api/datasets/export?exporter=" + formatName + "&persistentId=" + ds.getProtocol() + ":" + ds.getAuthority() + "/" + ds.getIdentifier() + "href", getExporterUrl(formatName, ds) ).add( "type", exporter.getMediaType() @@ -297,4 +295,9 @@ private String getPublicDownloadUrl(DataFile dataFile) { return FileUtil.getPublicDownloadUrl(systemConfig.getDataverseSiteUrl(), ((gid != null) ? gid.asString() : null), dataFile.getId()); } + + private String getExporterUrl(String formatName, Dataset ds) { + return systemConfig.getDataverseSiteUrl() + + "/api/datasets/export?exporter=" + formatName + "&persistentId=" + ds.getGlobalId().asString(); + } } diff --git a/src/test/java/edu/harvard/iq/dataverse/api/SignpostingIT.java b/src/test/java/edu/harvard/iq/dataverse/api/SignpostingIT.java index 4327aa26778..4e01d772c2d 100644 --- a/src/test/java/edu/harvard/iq/dataverse/api/SignpostingIT.java +++ b/src/test/java/edu/harvard/iq/dataverse/api/SignpostingIT.java @@ -16,6 +16,8 @@ import java.util.regex.Pattern; import jakarta.json.JsonObject; +import static org.hamcrest.CoreMatchers.endsWith; +import static org.hamcrest.CoreMatchers.is; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -56,6 +58,9 @@ public void testSignposting() { String datasetLandingPage = RestAssured.baseURI + "/dataset.xhtml?persistentId=" + datasetPid; System.out.println("Checking dataset landing page for Signposting: " + datasetLandingPage); Response getHtml = given().get(datasetLandingPage); + getHtml.then().assertThat() + .statusCode(OK.getStatusCode()) + .header("Link", endsWith("linkset?persistentId=" + datasetPid + "> ; rel=\"linkset\";type=\"application/linkset+json\"")); System.out.println("Link header: " + getHtml.getHeader("Link")); if (false) { @@ -104,6 +109,11 @@ public void testSignposting() { Response linksetResponse = given().accept(ContentType.JSON).get(linksetUrl); linksetResponse.prettyPrint(); + linksetResponse.then().assertThat() + .statusCode(OK.getStatusCode()) + .body("linkset[0].anchor", is(RestAssured.baseURI + "/dataset.xhtml?persistentId=" + datasetPid)) + .body("linkset[0].license.href", is("http://creativecommons.org/publicdomain/zero/1.0")) + .body("linkset[0].describedby[1].href", endsWith("persistentId=" + datasetPid)); String responseString = linksetResponse.getBody().asString(); System.out.println("response string: " + responseString); From a92366e7e0c377a17297a73741f5452647faa4fc Mon Sep 17 00:00:00 2001 From: Philip Durbin Date: Mon, 25 Nov 2024 12:11:07 -0500 Subject: [PATCH 4/6] fix test and update changelog about schema.org content type change #10542 The test file is used in InfoIT#testGetExportFormats --- doc/release-notes/10542-signposting.md | 2 ++ doc/sphinx-guides/source/api/changelog.rst | 4 ++++ src/test/resources/json/export-formats.json | 2 +- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/doc/release-notes/10542-signposting.md b/doc/release-notes/10542-signposting.md index b6429310323..f847e6ba94a 100644 --- a/doc/release-notes/10542-signposting.md +++ b/doc/release-notes/10542-signposting.md @@ -6,4 +6,6 @@ The output of HEAD, GET, and the Signposting "linkset" API have all been updated This provides a lightweight machine-readable way to first retrieve a list of links (via a HTTP HEAD request, for example) to each available metadata export format and then follow up with a request for the export format of interest. +In addition, the content type for the `schema.org` dataset metadata export format has been corrected. It was `application/json` and now it is `application/ld+json`. + See also [the docs](https://preview.guides.gdcc.io/en/develop/api/native-api.html#retrieve-signposting-information) and #10542. diff --git a/doc/sphinx-guides/source/api/changelog.rst b/doc/sphinx-guides/source/api/changelog.rst index 92cd4fc941b..5d2e511688b 100644 --- a/doc/sphinx-guides/source/api/changelog.rst +++ b/doc/sphinx-guides/source/api/changelog.rst @@ -7,6 +7,10 @@ This API changelog is experimental and we would love feedback on its usefulness. :local: :depth: 1 +v6.5 +---- +- The content type for the ``schema.org`` dataset metadata export format has been corrected. It was ``application/json`` and now it is ``application/ld+json``. See also :ref:`export-dataset-metadata-api`. + v6.4 ---- diff --git a/src/test/resources/json/export-formats.json b/src/test/resources/json/export-formats.json index b4dc0168629..65fc746ee23 100644 --- a/src/test/resources/json/export-formats.json +++ b/src/test/resources/json/export-formats.json @@ -36,7 +36,7 @@ }, "schema.org": { "displayName": "Schema.org JSON-LD", - "mediaType": "application/json", + "mediaType": "application/ld+json", "isHarvestable": false, "isVisibleInUserInterface": true }, From 8a0102bb89d402731fff8b111405588343d2af75 Mon Sep 17 00:00:00 2001 From: Philip Durbin Date: Mon, 25 Nov 2024 12:12:01 -0500 Subject: [PATCH 5/6] fix broken header #10542 --- doc/sphinx-guides/source/api/native-api.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/sphinx-guides/source/api/native-api.rst b/doc/sphinx-guides/source/api/native-api.rst index 5ff527f4e39..d98748da74d 100644 --- a/doc/sphinx-guides/source/api/native-api.rst +++ b/doc/sphinx-guides/source/api/native-api.rst @@ -1392,6 +1392,7 @@ Both forms are valid according to Google's Structured Data Testing Tool at https The standard has further evolved into a format called Croissant. For details, see :ref:`schema.org-head` in the Admin Guide. The ``schema.org`` format changed after Dataverse 6.4 as well. Previously its content type was "application/json" but now it is "application/ld+json". + List Files in a Dataset ~~~~~~~~~~~~~~~~~~~~~~~ From f7046515c5bd0ee128f31030d892d5fb75f27505 Mon Sep 17 00:00:00 2001 From: Philip Durbin Date: Mon, 25 Nov 2024 12:20:23 -0500 Subject: [PATCH 6/6] remove baseurl to get test to pass on Jenkins #10542 Before this PR... In development: Expected: is "http://localhost:8080/dataset.xhtml?persistentId=doi:10.5072/FK2/6A3292" Actual: is "http://localhost:8080/dataset.xhtml?persistentId=doi:10.5072/FK2/6A3292" On Jenkins Expected: is "http://localhost:8080/dataset.xhtml?persistentId=doi:10.5072/FK2/6A3292" Actual: http://ec2-3-225-221-142.compute-1.amazonaws.com/dataset.xhtml?persistentId=doi:10.5072/FK2/6A3292 So we'll change to just "endsWith" since we aren't actually testing the baseurl, just the datasetPid which we fixed up in ca93d60685. --- src/test/java/edu/harvard/iq/dataverse/api/SignpostingIT.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/edu/harvard/iq/dataverse/api/SignpostingIT.java b/src/test/java/edu/harvard/iq/dataverse/api/SignpostingIT.java index 4e01d772c2d..679d1e79aa1 100644 --- a/src/test/java/edu/harvard/iq/dataverse/api/SignpostingIT.java +++ b/src/test/java/edu/harvard/iq/dataverse/api/SignpostingIT.java @@ -111,7 +111,7 @@ public void testSignposting() { linksetResponse.prettyPrint(); linksetResponse.then().assertThat() .statusCode(OK.getStatusCode()) - .body("linkset[0].anchor", is(RestAssured.baseURI + "/dataset.xhtml?persistentId=" + datasetPid)) + .body("linkset[0].anchor", endsWith("/dataset.xhtml?persistentId=" + datasetPid)) .body("linkset[0].license.href", is("http://creativecommons.org/publicdomain/zero/1.0")) .body("linkset[0].describedby[1].href", endsWith("persistentId=" + datasetPid));