Skip to content

CLARIN-DSpace v9/Port #1384 (CMDI ResourceRef machine-actionable download links) to the v9 base - #1395

Merged
milanmajchrak merged 1 commit into
dtq-dev-9-basefrom
ufal/port-1384-9-base
Aug 10, 2026
Merged

CLARIN-DSpace v9/Port #1384 (CMDI ResourceRef machine-actionable download links) to the v9 base#1395
milanmajchrak merged 1 commit into
dtq-dev-9-basefrom
ufal/port-1384-9-base

Conversation

@Kasinhou

Copy link
Copy Markdown

Post-snapshot sync dtq-dev → dtq-dev-9-base

Port of dataquest-dev#1384 (itself a port of ufal#1384 by @kosarko, upstream commit 82e33e817a) to the v9 base.

6114281c15 (dtq-dev #1384) — CMDI ResourceRef machine-actionable download links — PORT

ProcessBitstreams in lindat_cmdi.xsl now emits
${dspace.server.url}/api/core/bitstreams/handle/<handle>/<url-encoded-filename>
instead of the UI-only ${dspace.ui.url}/bitstream/handle/...?sequence=n link, which only resolved through the Angular legacy-URL redirect in a browser and was useless to a machine client. Filenames are URL-encoded (fnx:encode-for-uri), and only ORIGINAL-bundle bitstreams are listed, since the download endpoint serves nothing else.

Clean conflict-free cherry-pick — no v9 adaptations needed. Verified against the v9 base:

  • lindat_cmdi.xsl has an identical pre-image here ($dsURL declared at line 28, used in exactly one place — ProcessBitstreams' ResourceRef), and the fnx prefix (http://www.w3.org/2005/xpath-functions) that encode-for-uri needs is already declared and listed in exclude-result-prefixes.
  • CmdiDownloadLinkIT.java is a new file and needs no javax→jakarta conversion: its javax.xml.* imports are JDK JAXP, not Java EE.
  • Every API the new IT touches exists on this branch: SolrOAIReindexer#reindexItem(Item) + its solrServerResolver field, DSpaceItemRepositoryResolver's itemRepository field, MockSolrServer, XOAICacheService / SolrServerResolver / ItemRepositoryResolver, BitstreamBuilder#createBitstream(ctx, item, is, bundleName), Constants.LICENSE_BUNDLE_NAME / LICENSE_BITSTREAM_NAME, and BitstreamByHandleRestController serving GET /api/core/bitstreams/handle/{prefix}/{suffix}/{filename} for ORIGINAL-bundle bitstreams only.
  • spring-boot 3.5.14 still ships @MockBean (deprecated since 3.4); the sibling OAIpmhIT on this branch uses it the same way, so no test-harness change.

Gates

  • Ported files are byte-identical to 6114281c15 (git diff 6114281c15 HEAD -- <both paths> is empty).
  • Full reactor mvn install -DskipTests — BUILD SUCCESS, 0 Checkstyle violations.
  • CmdiDownloadLinkIT run against a testEnvironment.zip rebuilt from this tree (so the new XSL is the one under test): Tests run: 1, Failures: 0, Errors: 0, Skipped: 0. The test harvests the CMDI record via OAI-PMH GetRecord, asserts the ResourceRef equals the by-handle URL with a %20-encoded filename, asserts the legacy /bitstream/handle/ + ?sequence= forms and the LICENSE bitstream are absent, then downloads the file from that URL and compares content.
  • No other test asserts on the CMDI crosswalk output — ClarinRefBoxControllerIT only checks the cmdi export-format URL/metadata, not ResourceRef. CI Unit+Integration jobs are the record gate.

Note

The prior v9-base port commits reference CLARIN_V9_POST_SNAPSHOT_SYNC_ACCEPTANCE.md / CLARIN_V9_PARITY_BACKLOG.md, neither of which is tracked on this branch, so this port carries no "Fulfils §5 / card" line. If those planning docs should get a card for 6114281c15, say so and I'll add it.

🤖 Generated with Claude Code

…fal#1384)

Emit ${dspace.server.url}/api/core/bitstreams/handle/<handle>/<filename>
(the endpoint used by the item-page curl instructions) instead of the
UI-only ${dspace.ui.url}/bitstream/handle/...?sequence=n link, which only
worked through the Angular legacy-URL redirect in a browser.

- URL-encode the filename (encode-for-uri), names with spaces were
  already broken for curl
- list only ORIGINAL-bundle bitstreams; the download endpoint serves
  nothing else, so THUMBNAIL/TEXT entries would have been dead links
- add CmdiDownloadLinkIT: harvests the CMDI record via OAI-PMH GetRecord,
  extracts the ResourceRef and downloads the file from it
- restrict the ResourceRef XPath to bitstream proxies (id starting with "_")
  so source-URI proxies can't match; harden the test XML parser (secure
  processing, disallow DOCTYPE); NamespaceContext#getPrefixes returns an
  empty iterator, not null

(cherry picked from commit 82e33e8 on ufal/clarin-dspace)
(cherry picked from commit 6114281 on dtq-dev)

Clean conflict-free pick, no v9 adaptations needed. Verified against the v9 base:
- lindat_cmdi.xsl has an identical pre-image here ($dsURL declared at line 28 and
  used in exactly one place, ProcessBitstreams' ResourceRef), and the fnx prefix
  (http://www.w3.org/2005/xpath-functions) that encode-for-uri needs is already
  declared and listed in exclude-result-prefixes.
- CmdiDownloadLinkIT.java is a new file and needs no javax->jakarta conversion:
  its javax.xml.* imports are JDK JAXP, not Java EE.
- Every API the new IT touches exists on this branch: SolrOAIReindexer
  #reindexItem(Item) plus its solrServerResolver field, DSpaceItemRepositoryResolver's
  itemRepository field, MockSolrServer, XOAICacheService / SolrServerResolver /
  ItemRepositoryResolver, BitstreamBuilder#createBitstream(ctx, item, is, bundleName),
  Constants.LICENSE_BUNDLE_NAME / LICENSE_BITSTREAM_NAME, and
  BitstreamByHandleRestController serving GET /api/core/bitstreams/handle/{prefix}/
  {suffix}/{filename} for ORIGINAL-bundle bitstreams only.
- spring-boot 3.5.14 still ships @MockBean (deprecated since 3.4); the sibling
  OAIpmhIT on this branch uses it the same way, so no test-harness change.

Co-authored-by: Ondřej Košarko <ko_ok@centrum.cz>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR ports CLARIN-DSpace change #1384 to the v9 base to ensure CMDI OAI-PMH cmd:ResourceRef values are machine-actionable download links pointing to the REST by-handle bitstream endpoint, instead of UI-only legacy bitstream URLs.

Changes:

  • Updated the CMDI XSL crosswalk to emit ${dspace.server.url}/api/core/bitstreams/handle/<handle>/<url-encoded-filename> and to list only ORIGINAL-bundle bitstreams.
  • Added an end-to-end integration test which harvests a CMDI record via OAI-PMH, validates the emitted link(s), and downloads the referenced bitstream to verify content.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
dspace/config/crosswalks/oai/metadataFormats/lindat_cmdi.xsl Switches CMDI ResourceRef output to REST by-handle download URLs with URL-encoded filenames, restricted to ORIGINAL bundle bitstreams.
dspace-server-webapp/src/test/java/org/dspace/app/oai/CmdiDownloadLinkIT.java New integration test covering CMDI ResourceRef link format, exclusion of legacy links/LICENSE bitstream, and successful download/content verification.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@milanmajchrak
milanmajchrak merged commit ea8b872 into dtq-dev-9-base Aug 10, 2026
17 of 18 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants