Skip to content

Commit

Permalink
Resolves to a context even if path is wrong
Browse files Browse the repository at this point in the history
  • Loading branch information
gunnarvelle committed Dec 2, 2024
1 parent bc6d53d commit c69eb10
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 23 deletions.
42 changes: 24 additions & 18 deletions src/main/java/no/ndla/taxonomy/service/UrlResolverServiceImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -157,27 +157,33 @@ public Optional<ResolvedUrl> resolveUrl(String path, String language) {
final var normalizedPath =
resolvedPathComponents.stream().map(Node::getPathPart).collect(Collectors.joining());
final var leafNode = resolvedPathComponents.getLast();
TaxonomyContext context = leafNode.getContexts().stream()
Optional<TaxonomyContext> context = leafNode.getContexts().stream()
.filter(ctx -> ctx.path().equals(normalizedPath))
.findFirst()
.orElseThrow(
() -> new NotFoundServiceException("Element with path " + path + " could not be found"));
.findFirst();

final var resolvedUrl = new ResolvedUrl();
resolvedUrl.setContentUri(leafNode.getContentUri());
resolvedUrl.setId(URI.create(context.publicId()));
resolvedUrl.setParents(
context.parentIds().stream().map(URI::create).toList().reversed());
resolvedUrl.setName(context.name().fromLanguage(language));
resolvedUrl.setPath(context.path());
resolvedUrl.setUrl(PrettyUrlUtil.createPrettyUrl(
Optional.ofNullable(context.rootName()),
context.name(),
language,
context.contextId(),
context.nodeType())
.orElse(context.path()));

// Pick eiter the context matching path or the primary context
context.or(() -> leafNode.pickContext(Optional.empty(), Optional.empty(), Optional.empty(), Set.of()))
.map(Optional::of)
.orElseThrow(() -> new NotFoundServiceException("No context found for path"))
.ifPresent(ctx -> {
resolvedUrl.setExactMatch(context.isPresent());
resolvedUrl.setContentUri(leafNode.getContentUri());
resolvedUrl.setId(URI.create(ctx.publicId()));
resolvedUrl.setParents(ctx.parentIds().stream()
.map(URI::create)
.toList()
.reversed());
resolvedUrl.setName(ctx.name().fromLanguage(language));
resolvedUrl.setPath(ctx.path());
resolvedUrl.setUrl(PrettyUrlUtil.createPrettyUrl(
Optional.ofNullable(ctx.rootName()),
ctx.name(),
language,
ctx.contextId(),
ctx.nodeType())
.orElse(ctx.path()));
});
return Optional.of(resolvedUrl);
} catch (NotFoundServiceException e) {
return Optional.empty();
Expand Down
12 changes: 12 additions & 0 deletions src/main/java/no/ndla/taxonomy/service/dtos/ResolvedUrl.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ public class ResolvedUrl {
@Schema(description = "Pretty url resource", example = "'/r/subject-name/resource-name/hash'")
private String url;

@JsonProperty
@Schema(description = "Is this an exact match for the provided path? False if this is another path to the same resource.")
private boolean exactMatch;

public URI getId() {
return id;
}
Expand Down Expand Up @@ -93,4 +97,12 @@ public String getUrl() {
public void setUrl(String url) {
this.url = url;
}

public boolean isExactMatch() {
return exactMatch;
}

public void setExactMatch(boolean exactMatch) {
this.exactMatch = exactMatch;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,8 @@ public void resolveEntitiesFromPath() {
t.resource("resource");
}));

builder.node(NodeType.RESOURCE, r -> r.publicId("urn:resource:2").name("Resource Name"));

// Four paths exists to the same resource:
// /subject:1/topic:1/resource:1
// /subject:2/topic:2/resource:2
Expand Down Expand Up @@ -387,12 +389,18 @@ public void resolveEntitiesFromPath() {
assertTrue(resolvedUrl.getUrl().startsWith("/f/biology/"));
}

// Test with a non-valid path
assertFalse(urlResolverService.resolveUrl("/subject:2/resource:1", "nb").isPresent());
// Test with a non-valid path to valid resource
{
var resolvedUrl = urlResolverService.resolveUrl("/subject:2/resource:1", "nb");
assertTrue(resolvedUrl.isPresent());
assertFalse(resolvedUrl.get().isExactMatch());
}

// Test with a non-context
assertFalse(urlResolverService.resolveUrl("/topic:1/resource:1", "nb").isPresent());
assertFalse(urlResolverService.resolveUrl("/topic:2/resource:1", "nb").isPresent());
// Test with non-context node
{
assertFalse(urlResolverService.resolveUrl("/topic:1/resource:2", "nb").isPresent());
assertFalse(urlResolverService.resolveUrl("/topic:2/resource:2", "nb").isPresent());
}

// Since topic3 is a context in itself, it would be valid to use it as root
{
Expand Down

0 comments on commit c69eb10

Please sign in to comment.