Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,33 @@
end

methods
function addLinkResolver(obj, resolver)
% Add a resolver instance to the registry (no duplicates by handle).
function addLinkResolver(obj, resolver, options)
% Add a resolver to the registry, at most one per IRI prefix.
%
% By default a resolver whose prefix is already registered is
% ignored, so registering at startup is idempotent. Pass
% Replace=true to swap the registered resolver for this one,
% keeping its position: a library that reconfigures, for example
% with a new server or credentials, re-registers rather than
% mutating the resolver it registered earlier.
arguments
obj (1,1) openminds.internal.resolver.LinkResolverRegistry
resolver (1,1) {mustBeA(resolver, "openminds.interface.LinkResolver")}
options.Replace (1,1) logical = false
end

if obj.hasResolverForPrefix(resolver.IRIPrefix)
% Already registered
return
end
existingIndex = obj.indexOfPrefix(resolver.IRIPrefix);

obj.LinkResolvers{end+1} = resolver;
if isempty(existingIndex)
obj.LinkResolvers{end+1} = resolver;
elseif options.Replace
obj.LinkResolvers{existingIndex} = resolver;
end
% Otherwise already registered; keep the existing resolver.
end

function tf = hasResolverForPrefix(obj, iriPrefix)
tf = any( cellfun(@(r) r.IRIPrefix == iriPrefix, obj.LinkResolvers) );
tf = ~isempty( obj.indexOfPrefix(iriPrefix) );
end

function resolver = getLinkResolver(obj, IRI)
Expand Down Expand Up @@ -70,6 +80,11 @@ function reset(obj)
end

methods (Access = private)
function index = indexOfPrefix(obj, iriPrefix)
% Position of the resolver registered for a prefix, or empty.
index = find( cellfun(@(r) r.IRIPrefix == iriPrefix, obj.LinkResolvers), 1 );
end

function promoteResolver(obj, index)
% promoteResolver - Reorder registry so the resolver at index is first
arguments
Expand Down
15 changes: 13 additions & 2 deletions code/internal/+openminds/registerLinkResolver.m
Original file line number Diff line number Diff line change
@@ -1,14 +1,25 @@
function registerLinkResolver(linkResolver)
function registerLinkResolver(linkResolver, options)
% registerLinkResolver - Register a link resolver in the link resolver registry
%
% openminds.registerLinkResolver(linkResolver) registers a resolver for
% the identifier prefix it declares. Registering a prefix that is
% already registered does nothing, so calling this from library startup
% code is idempotent.
%
% openminds.registerLinkResolver(linkResolver, Replace=true) replaces
% the resolver registered for that prefix with this one. Use this when
% a library reconfigures, for example connecting to a different server,
% and needs its new resolver to take effect.
%
% See also:
% openminds.interface.LinkResolver
% openminds.internal.resolver.InstanceResolver

arguments
linkResolver (1,1) {mustBeA(linkResolver, "openminds.interface.LinkResolver")}
options.Replace (1,1) logical = false
end

resolverRegistry = openminds.internal.resolver.LinkResolverRegistry.instance();
resolverRegistry.addLinkResolver(linkResolver);
resolverRegistry.addLinkResolver(linkResolver, "Replace", options.Replace);
end
27 changes: 27 additions & 0 deletions tools/tests/unitTests/ResolverTest.m
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,33 @@ function testResolverRegistryPromotesUsedResolver(testCase)
testCase.verifyEqual(registry.LinkResolvers{1}, mockResolver);
end

function testReplaceRegisteredResolver(testCase)
% A library that reconfigures needs its new resolver to take
% effect. Without Replace the first registration wins; with it,
% the resolver for that prefix is swapped and keeps its position.

registry = openminds.internal.resolver.LinkResolverRegistry.instance();

firstResolver = ommtest.helper.mock.MockLinkResolver();
secondResolver = ommtest.helper.mock.MockLinkResolver();
openminds.registerLinkResolver(firstResolver);

openminds.registerLinkResolver(secondResolver);
registered = registry.getLinkResolver("https://mock.io/x");
testCase.verifyTrue(registered == firstResolver, ...
'Without Replace, the first registration should win.')

openminds.registerLinkResolver(secondResolver, "Replace", true);
registered = registry.getLinkResolver("https://mock.io/x");
testCase.verifyTrue(registered == secondResolver, ...
'With Replace, the new resolver should take over the prefix.')

testCase.verifyEqual( ...
sum(cellfun(@(r) isa(r, 'ommtest.helper.mock.MockLinkResolver'), ...
registry.LinkResolvers)), 1, ...
'Replacing should not add a second resolver for the prefix.')
end

function testNoDuplicateResolvers(testCase)
% Test that duplicate resolvers are not added
resolver = ommtest.helper.mock.MockLinkResolver();
Expand Down
Loading