Skip to content

ILLDEV-423 metadata lookup#648

Draft
adamdickmeiss wants to merge 17 commits into
mainfrom
ILLDEV-423-metadata-lookup
Draft

ILLDEV-423 metadata lookup#648
adamdickmeiss wants to merge 17 commits into
mainfrom
ILLDEV-423-metadata-lookup

Conversation

@adamdickmeiss

@adamdickmeiss adamdickmeiss commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Copilot AI review requested due to automatic review settings June 29, 2026 10:28
@adamdickmeiss adamdickmeiss changed the title Illdev 423 metadata lookup ILLDEV-423 metadata lookup Jun 29, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 introduces configurable “metadata lookup” behavior that can update ISO18626 bibliographic metadata using holdings lookup results, controlled via new Directory configuration fields.

Changes:

  • Extends the Directory API schema with metadataUpdateMode (replace/merge/none/auto) and metadataFormat (marc21).
  • Adds a new broker/metadataupdate package and integrates metadata-update behavior into supplier location, patron-request creation, and outbound ISO18626 request construction.
  • Adds end-to-end and unit tests plus XML testdata to validate replace vs merge behavior.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
directory/directory_api.yaml Adds schema enums/fields for metadata update mode and format.
broker/test/testdata/request-metadata-update.xml New ISO18626 request fixture used by E2E tests.
broker/test/service/e2e_test.go Adds E2E coverage for metadata update replace/merge modes and hardens event formatting.
broker/service/supplierlocator.go Applies holdings-derived metadata updates to stored transaction data (when enabled).
broker/patron_request/api/api-handler.go Optionally applies holdings-derived metadata updates during patron request creation.
broker/metadataupdate/metadataupdate.go New implementation for applying replace/merge/none bibliographic metadata updates.
broker/metadataupdate/metadataupdate_test.go Unit tests for metadata update behavior.
broker/holdings/creator.go Adds a MetadataSettings struct used for metadata update configuration.
broker/holdings/creator_test.go Adds tests for metadata settings defaults/config and update-mode/format resolution helpers.
broker/holdings/creator_impl.go Implements metadata settings parsing and mode/format/hint resolution helpers.
broker/client/client.go Alters outbound request message creation to honor metadata update mode.
broker/app/app.go Wires new dependencies into the patron request API handler.

Comment thread broker/metadataupdate/metadataupdate.go
Comment thread broker/metadataupdate/metadataupdate.go
Comment thread broker/client/client.go Outdated
Comment on lines +771 to +781
bibliographicInfo := trCtx.transaction.IllTransactionData.BibliographicInfo
if resolvedMode == directory.None {
// Backward compatibility: preserve historical request-message behavior when metadata updates are disabled.
bibliographicInfo.SupplierUniqueRecordId = trCtx.selectedSupplier.LocalID.String
} else {
bibliographicInfo = metadataupdate.ApplyBibliographicUpdate(
bibliographicInfo,
metadataupdate.MetadataFields{LocalIdentifier: trCtx.selectedSupplier.LocalID.String},
resolvedMode,
)
}
Comment thread broker/patron_request/api/api-handler.go Outdated
@adamdickmeiss adamdickmeiss marked this pull request as draft June 29, 2026 10:39
Copilot AI review requested due to automatic review settings June 29, 2026 11:01

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 12 out of 12 changed files in this pull request and generated 3 comments.

Comment on lines +50 to +72
func appendCrosslinkMetadata(existing []iso18626.BibliographicRecordId, metadata MetadataFields, mergeOnly bool) []iso18626.BibliographicRecordId {
values := map[string]string{
"location": metadata.Location,
"shelvingLocation": metadata.ShelvingLocation,
"callNumber": metadata.CallNumber,
"itemId": metadata.ItemId,
}
for code, value := range values {
trimmed := strings.TrimSpace(value)
if trimmed == "" {
continue
}
if mergeOnly && hasCrosslinkCode(existing, code) {
continue
}
scheme := "crosslink"
existing = append(existing, iso18626.BibliographicRecordId{
BibliographicRecordIdentifierCode: iso18626.TypeSchemeValuePair{Text: code, Scheme: &scheme},
BibliographicRecordIdentifier: trimmed,
})
}
return existing
}
Comment on lines +74 to +92
func stripCrosslinkMetadataCodes(existing []iso18626.BibliographicRecordId) []iso18626.BibliographicRecordId {
result := make([]iso18626.BibliographicRecordId, 0, len(existing))
for _, entry := range existing {
if isCrosslinkMetadataCode(entry.BibliographicRecordIdentifierCode.Text) {
continue
}
result = append(result, entry)
}
return result
}

func hasCrosslinkCode(existing []iso18626.BibliographicRecordId, code string) bool {
for _, entry := range existing {
if strings.EqualFold(strings.TrimSpace(entry.BibliographicRecordIdentifierCode.Text), strings.TrimSpace(code)) {
return true
}
}
return false
}
Comment thread broker/patron_request/api/api-handler.go Outdated
Copilot AI review requested due to automatic review settings June 29, 2026 11:07

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 12 out of 12 changed files in this pull request and generated 3 comments.

Comment on lines +50 to +72
func appendCrosslinkMetadata(existing []iso18626.BibliographicRecordId, metadata MetadataFields, mergeOnly bool) []iso18626.BibliographicRecordId {
values := map[string]string{
"location": metadata.Location,
"shelvingLocation": metadata.ShelvingLocation,
"callNumber": metadata.CallNumber,
"itemId": metadata.ItemId,
}
for code, value := range values {
trimmed := strings.TrimSpace(value)
if trimmed == "" {
continue
}
if mergeOnly && hasCrosslinkCode(existing, code) {
continue
}
scheme := "crosslink"
existing = append(existing, iso18626.BibliographicRecordId{
BibliographicRecordIdentifierCode: iso18626.TypeSchemeValuePair{Text: code, Scheme: &scheme},
BibliographicRecordIdentifier: trimmed,
})
}
return existing
}
Comment thread broker/patron_request/api/api-handler.go Outdated
Comment thread broker/client/client.go Outdated
Comment on lines +765 to +781
metadataSettings := holdings.GetMetadataSettings(trCtx.requester.CustomData)
lookupHint := holdings.LookupHintFromParams(holdings.LookupParamsFromBibliographicInfo(
trCtx.transaction.IllTransactionData.BibliographicInfo,
"",
))
resolvedMode := holdings.ResolveMetadataUpdateMode(string(metadataSettings.Mode), lookupHint)
bibliographicInfo := trCtx.transaction.IllTransactionData.BibliographicInfo
if resolvedMode == directory.None {
// Backward compatibility: preserve historical request-message behavior when metadata updates are disabled.
bibliographicInfo.SupplierUniqueRecordId = trCtx.selectedSupplier.LocalID.String
} else {
bibliographicInfo = metadataupdate.ApplyBibliographicUpdate(
bibliographicInfo,
metadataupdate.MetadataFields{LocalIdentifier: trCtx.selectedSupplier.LocalID.String},
resolvedMode,
)
}
Copilot AI review requested due to automatic review settings June 30, 2026 11:48

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 12 out of 12 changed files in this pull request and generated 3 comments.

Comment thread broker/patron_request/api/api-handler.go Outdated
Comment thread broker/patron_request/api/api-handler.go Outdated
Comment thread broker/patron_request/api/api-handler.go
Copilot AI review requested due to automatic review settings June 30, 2026 12:13

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 12 out of 12 changed files in this pull request and generated 3 comments.

Comment thread broker/client/client.go Outdated
Comment on lines +765 to +781
metadataSettings := holdings.GetMetadataSettings(trCtx.requester.CustomData)
lookupHint := holdings.LookupHintFromParams(holdings.LookupParamsFromBibliographicInfo(
trCtx.transaction.IllTransactionData.BibliographicInfo,
"",
))
resolvedMode := holdings.ResolveMetadataUpdateMode(string(metadataSettings.Mode), lookupHint)
bibliographicInfo := trCtx.transaction.IllTransactionData.BibliographicInfo
if resolvedMode == directory.None {
// Backward compatibility: preserve historical request-message behavior when metadata updates are disabled.
bibliographicInfo.SupplierUniqueRecordId = trCtx.selectedSupplier.LocalID.String
} else {
bibliographicInfo = metadataupdate.ApplyBibliographicUpdate(
bibliographicInfo,
metadataupdate.MetadataFields{LocalIdentifier: trCtx.selectedSupplier.LocalID.String},
resolvedMode,
)
}
Comment on lines +74 to +83
func stripCrosslinkMetadataCodes(existing []iso18626.BibliographicRecordId) []iso18626.BibliographicRecordId {
result := make([]iso18626.BibliographicRecordId, 0, len(existing))
for _, entry := range existing {
if isCrosslinkMetadataCode(entry.BibliographicRecordIdentifierCode.Text) {
continue
}
result = append(result, entry)
}
return result
}
Comment on lines +85 to +92
func hasCrosslinkCode(existing []iso18626.BibliographicRecordId, code string) bool {
for _, entry := range existing {
if strings.EqualFold(strings.TrimSpace(entry.BibliographicRecordIdentifierCode.Text), strings.TrimSpace(code)) {
return true
}
}
return false
}
Copilot AI review requested due to automatic review settings June 30, 2026 12:57

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated 5 comments.

Comment on lines +34 to +39
if mode == directory.Replace {
updated.SupplierUniqueRecordId = metadata.LocalIdentifier
updated.BibliographicRecordId = stripCrosslinkMetadataCodes(updated.BibliographicRecordId)
updated.BibliographicRecordId = appendCrosslinkMetadata(updated.BibliographicRecordId, metadata, false)
return updated
}
Comment on lines +158 to +176
firstHolding := holdingsResult[0]

if requester.Vendor != string(directory.CrossLink) {
holdingsConfigSource := requester.CustomData
if len(consortiumPeers) > 0 && consortiumPeers[0].CustomData.HoldingsConfig != nil {
holdingsConfigSource = consortiumPeers[0].CustomData
}
metadataSettings := holdings.GetMetadataSettings(holdingsConfigSource)
lookupHint := holdings.LookupHintFromParams(holdingsParams)
resolvedMode := holdings.ResolveMetadataUpdateMode(string(metadataSettings.Mode), lookupHint)
if resolvedMode != directory.None {
if !metadataupdate.SupportsFormat(metadataSettings.Format) {
return events.LogErrorAndReturnResult(ctx, "unsupported metadata format for metadata update", fmt.Errorf("unsupported metadata format: %s", metadataSettings.Format))
}
illTrans.IllTransactionData.BibliographicInfo = metadataupdate.ApplyBibliographicUpdate(
illTrans.IllTransactionData.BibliographicInfo,
metadataupdate.MetadataFields{LocalIdentifier: firstHolding.LocalIdentifier, Location: firstHolding.Location, ShelvingLocation: firstHolding.ShelvingLocation, CallNumber: firstHolding.CallNumber, ItemId: firstHolding.ItemId},
resolvedMode,
)
Comment on lines +951 to +958
test.WaitForPredicateToBeTrue(func() bool {
illTrans, err = illRepo.GetIllTransactionByRequesterRequestId(appCtx, getPgText(reqId))
if err != nil {
t.Errorf("failed to find ill transaction by requester request id %v", reqId)
}
return illTrans.LastSupplierStatus.String == string(iso18626.TypeStatusUnfilled) &&
illTrans.LastRequesterAction.String == "Request"
})
Comment on lines +935 to +938
// The outgoing SupplierUniqueRecordId after merge will still be "return-ISIL:META-MRG-SUP::WILLSUPPLY"
// (original preserved), which doesn't match a known supplier scenario, so the mock supplier
// responds with Unfilled. We wait for that terminal state before asserting the DB value.
stringData := strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(string(data),
Comment on lines +281 to +288
if !metadataupdate.SupportsFormat(settings.Format) {
return fmt.Errorf("unsupported metadata format: %s", settings.Format)
}
params := holdings.LookupParamsFromBibliographicInfo(illRequest.BibliographicInfo, illRequest.ServiceInfo)
resolvedMode := holdings.ResolveMetadataUpdateMode(string(settings.Mode), holdings.LookupHintFromParams(params))
if resolvedMode == directory.None {
return nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants