From 670ed3d8145b781ec7a483a1178a1d117d1f1b12 Mon Sep 17 00:00:00 2001 From: Gunnar Velle Date: Mon, 14 Oct 2024 09:31:45 +0200 Subject: [PATCH 1/4] Proxy subjects controller --- .../java/no/ndla/taxonomy/rest/v1/Nodes.java | 5 +- .../no/ndla/taxonomy/rest/v1/Subjects.java | 197 ++++-------------- .../ndla/taxonomy/rest/v1/SubjectsTest.java | 4 +- 3 files changed, 47 insertions(+), 159 deletions(-) diff --git a/src/main/java/no/ndla/taxonomy/rest/v1/Nodes.java b/src/main/java/no/ndla/taxonomy/rest/v1/Nodes.java index 8f653d27..1e650670 100644 --- a/src/main/java/no/ndla/taxonomy/rest/v1/Nodes.java +++ b/src/main/java/no/ndla/taxonomy/rest/v1/Nodes.java @@ -213,6 +213,7 @@ public SearchResultDTO getNodePage( Optional language, @Parameter(name = "page", description = "The page to fetch") Optional page, @Parameter(name = "pageSize", description = "Size of page to fetch") Optional pageSize, + @Parameter(name = "nodeType", description = "Filter by nodeType") Optional nodeType, @Parameter(name = "includeContexts", description = "Include all contexts") @RequestParam(value = "includeContexts", required = false, defaultValue = "true") Optional includeContexts, @@ -227,7 +228,9 @@ public SearchResultDTO getNodePage( } if (page.get() < 1) throw new IllegalArgumentException("page parameter must be bigger than 0"); - var ids = nodeRepository.findIdsPaginated(PageRequest.of(page.get() - 1, pageSize.get())); + var ids = nodeType.map( + nt -> nodeRepository.findIdsByTypePaginated(PageRequest.of(page.get() - 1, pageSize.get()), nt)) + .orElseGet(() -> nodeRepository.findIdsPaginated(PageRequest.of(page.get() - 1, pageSize.get()))); var results = nodeRepository.findByIds(ids.getContent()); var contents = results.stream() .map(node -> new NodeDTO( diff --git a/src/main/java/no/ndla/taxonomy/rest/v1/Subjects.java b/src/main/java/no/ndla/taxonomy/rest/v1/Subjects.java index 6c21f0bb..f3eb2b0c 100644 --- a/src/main/java/no/ndla/taxonomy/rest/v1/Subjects.java +++ b/src/main/java/no/ndla/taxonomy/rest/v1/Subjects.java @@ -12,23 +12,19 @@ import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import java.net.URI; -import java.util.*; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.stream.Collectors; +import java.util.List; +import java.util.Optional; import no.ndla.taxonomy.config.Constants; import no.ndla.taxonomy.domain.Node; -import no.ndla.taxonomy.domain.NodeConnection; import no.ndla.taxonomy.domain.NodeType; -import no.ndla.taxonomy.domain.exceptions.NotFoundException; -import no.ndla.taxonomy.repositories.NodeConnectionRepository; import no.ndla.taxonomy.repositories.NodeRepository; import no.ndla.taxonomy.rest.v1.commands.SubjectPostPut; -import no.ndla.taxonomy.service.*; +import no.ndla.taxonomy.service.ContextUpdaterService; +import no.ndla.taxonomy.service.NodeService; +import no.ndla.taxonomy.service.QualityEvaluationService; import no.ndla.taxonomy.service.dtos.NodeChildDTO; import no.ndla.taxonomy.service.dtos.NodeDTO; import no.ndla.taxonomy.service.dtos.SearchResultDTO; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.data.domain.PageRequest; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; @@ -38,33 +34,19 @@ @RestController @RequestMapping(path = {"/v1/subjects", "/v1/subjects/"}) public class Subjects extends CrudControllerWithMetadata { - private final TreeSorter topicTreeSorter; - private final RecursiveNodeTreeService recursiveNodeTreeService; + private final Nodes nodes; private final NodeService nodeService; - private final NodeRepository nodeRepository; - private final NodeConnectionRepository nodeConnectionRepository; - private final SearchService searchService; - - @Value(value = "${new.url.separator:false}") - private boolean newUrlSeparator; public Subjects( - TreeSorter treeSorter, + Nodes nodes, ContextUpdaterService contextUpdaterService, - RecursiveNodeTreeService recursiveNodeTreeService, NodeService nodeService, NodeRepository nodeRepository, - NodeConnectionRepository nodeConnectionRepository, - QualityEvaluationService qualityEvaluationService, - SearchService searchService) { + QualityEvaluationService qualityEvaluationService) { super(nodeRepository, contextUpdaterService, nodeService, qualityEvaluationService); - this.topicTreeSorter = treeSorter; - this.recursiveNodeTreeService = recursiveNodeTreeService; + this.nodes = nodes; this.nodeService = nodeService; - this.nodeRepository = nodeRepository; - this.nodeConnectionRepository = nodeConnectionRepository; - this.searchService = searchService; } @Deprecated @@ -77,22 +59,23 @@ public List getAllSubjects( Optional language, @Parameter(description = "Filter by key and value") @RequestParam(value = "key", required = false) Optional key, - @Parameter(description = "Fitler by key and value") @RequestParam(value = "value", required = false) + @Parameter(description = "Filter by key and value") @RequestParam(value = "value", required = false) Optional value, @Parameter(description = "Filter by visible") @RequestParam(value = "isVisible", required = false) Optional isVisible) { - MetadataFilters metadataFilters = new MetadataFilters(key, value, isVisible); - return nodeService.getNodesByType( + return nodes.getAllNodes( Optional.of(List.of(NodeType.SUBJECT)), - language.orElse(Constants.DefaultLanguage), + language, Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), + key, + value, + isVisible, Optional.empty(), - metadataFilters, - Optional.of(false), - false, + Optional.of(true), + true, Optional.empty(), Optional.empty()); } @@ -116,25 +99,23 @@ public SearchResultDTO searchSubjects( @Parameter(description = "ContentURIs to fetch for query") @RequestParam(value = "contentUris", required = false) Optional> contentUris) { - - return searchService.searchByNodeType( - query, - ids, - contentUris, + return nodes.searchNodes( language, - Optional.of(false), - false, pageSize, page, + query, + ids, + contentUris, Optional.of(List.of(NodeType.SUBJECT)), - Optional.empty(), + Optional.of(true), + true, Optional.empty(), Optional.empty()); } @Deprecated @GetMapping("/page") - @Operation(summary = "Gets all connections between node and children paginated") + @Operation(summary = "Gets all nodes paginated") @Transactional(readOnly = true) public SearchResultDTO getSubjectPage( @Parameter(description = "ISO-639-1 language code", example = "nb") @@ -142,27 +123,8 @@ public SearchResultDTO getSubjectPage( Optional language, @Parameter(name = "page", description = "The page to fetch") Optional page, @Parameter(name = "pageSize", description = "Size of page to fetch") Optional pageSize) { - if (page.isEmpty() || pageSize.isEmpty()) { - throw new IllegalArgumentException("Need both page and pageSize to return data"); - } - if (page.get() < 1) throw new IllegalArgumentException("page parameter must be bigger than 0"); - - var ids = - nodeRepository.findIdsByTypePaginated(PageRequest.of(page.get() - 1, pageSize.get()), NodeType.SUBJECT); - var results = nodeRepository.findByIds(ids.getContent()); - var contents = results.stream() - .map(node -> new NodeDTO( - Optional.empty(), - Optional.empty(), - node, - language.orElse("nb"), - Optional.empty(), - Optional.of(false), - false, - false, - newUrlSeparator)) - .collect(Collectors.toList()); - return new SearchResultDTO<>(ids.getTotalElements(), page.get(), pageSize.get(), contents); + return nodes.getNodePage( + language, page, pageSize, Optional.of(NodeType.SUBJECT), Optional.of(true), true, true); } @Deprecated @@ -176,7 +138,7 @@ public NodeDTO getSubject( @Parameter(description = "ISO-639-1 language code", example = "nb") @RequestParam(value = "language", required = false, defaultValue = Constants.DefaultLanguage) Optional language) { - return nodeService.getNode(id, language, Optional.empty(), Optional.empty(), Optional.of(false), false, true); + return nodes.getNode(id, Optional.empty(), Optional.empty(), Optional.of(true), true, true, language); } @Deprecated @@ -193,7 +155,7 @@ public void updateSubject( @RequestBody @Schema(name = "SubjectPOST") SubjectPostPut command) { - updateEntity(id, command); + nodes.updateEntity(id, command); } @Deprecated @@ -207,7 +169,7 @@ public ResponseEntity createSubject( @Parameter(name = "subject", description = "The new subject") @RequestBody @Schema(name = "SubjectPUT") SubjectPostPut command) { final var subject = new Node(NodeType.SUBJECT); - return createEntity(subject, command); + return nodes.createEntity(subject, command); } @Deprecated @@ -226,91 +188,16 @@ public List getSubjectChildren( @RequestParam(value = "recursive", required = false, defaultValue = "false") boolean recursive, @Parameter(description = "Select by relevance. If not specified, all nodes will be returned.") - @RequestParam(value = "relevance", required = false, defaultValue = "") - URI relevance) { - final var subject = - nodeRepository.findFirstByPublicId(id).orElseThrow(() -> new NotFoundException("Subject", id)); - - final List childrenIds; - - if (recursive) { - childrenIds = recursiveNodeTreeService.getRecursiveNodes(subject).stream() - .map(RecursiveNodeTreeService.TreeElement::getId) - .collect(Collectors.toList()); - } else { - childrenIds = subject.getChildConnections().stream() - .map(NodeConnection::getChild) - .filter(Optional::isPresent) - .map(Optional::get) - .map(Node::getPublicId) - .collect(Collectors.toList()); - } - - final var relevanceArgument = relevance == null || relevance.toString().equals("") ? null : relevance; - - final var children = - nodeConnectionRepository.findAllByChildIdIncludeTranslationsAndCachedUrlsAndFilters(childrenIds); - - final var returnList = new ArrayList(); - - final var connections = children.stream() - .filter(nodeConnection -> { - var child = nodeConnection.getChild(); - var relevanceFilter = searchForRelevance(nodeConnection, relevanceArgument, children); - return child.isPresent() && child.get().getNodeType() == NodeType.TOPIC && relevanceFilter; - }) - .toList(); - - connections.stream() - .map(nodeConnection -> new NodeChildDTO( - Optional.of(subject), - nodeConnection, - language.orElse(Constants.DefaultLanguage), - Optional.of(false), - false, - true, - newUrlSeparator)) - .forEach(returnList::add); - - var filtered = returnList.stream() - .filter(childDTO -> childrenIds.contains(childDTO.getParentId()) - || subject.getPublicId().equals(childDTO.getParentId())) - .toList(); - - // Remove duplicates from the list - // List is sorted by parent, so we assume that any subtree that has a duplicate parent also - // are repeated with the same subtree - // on the duplicates, so starting to remove duplicates should not leave any parent-less - - // (Don't know how much it makes sense to sort the list by parent and rank when duplicates - // are removed, but old code did) - return topicTreeSorter.sortList(filtered).stream().distinct().collect(Collectors.toList()); - } - - private boolean searchForRelevance( - NodeConnection connection, URI relevancePublicId, Collection children) { - if (relevancePublicId == null) { - return true; - } - - final var foundFilter = new AtomicBoolean(false); - Node node = connection.getChild().orElse(null); - - if (node != null) { - if (connection.getRelevance().isPresent()) { - foundFilter.set(connection.getRelevance().get().getPublicId().equals(relevancePublicId)); - } - - children.stream().filter(st -> st.getParent().isPresent()).forEach(nodeConnection -> { - if (nodeConnection.getParent().get().getId().equals(node.getId())) { - if (searchForRelevance(nodeConnection, relevancePublicId, children)) { - foundFilter.set(true); - } - } - }); - } - - return foundFilter.get(); + @RequestParam(value = "relevance", required = false) + Optional relevance) { + var children = nodes.getChildren( + id, Optional.of(List.of(NodeType.TOPIC)), recursive, language, Optional.of(true), true, true); + return relevance + .map(rel -> children.stream() + .filter(node -> node.getRelevanceId().isPresent() + && node.getRelevanceId().get().equals(rel)) + .toList()) + .orElse(children); } @Deprecated @@ -322,7 +209,7 @@ private boolean searchForRelevance( @ResponseStatus(HttpStatus.NO_CONTENT) @Transactional public void deleteEntity(@PathVariable("id") URI id) { - nodeService.delete(id); + nodes.deleteEntity(id); } @Deprecated @@ -347,8 +234,6 @@ public List getSubjectResources( @Parameter(description = "Select by relevance. If not specified, all resources will be returned.") @RequestParam(value = "relevance", required = false) Optional relevance) { - - return nodeService.getResourcesByNodeId( - subjectId, resourceTypeIds, relevance, language, true, Optional.of(false), false, true); + return nodes.getResources(subjectId, language, Optional.of(true), true, true, true, resourceTypeIds, relevance); } } diff --git a/src/test/java/no/ndla/taxonomy/rest/v1/SubjectsTest.java b/src/test/java/no/ndla/taxonomy/rest/v1/SubjectsTest.java index 545f4ce9..4662a2c9 100644 --- a/src/test/java/no/ndla/taxonomy/rest/v1/SubjectsTest.java +++ b/src/test/java/no/ndla/taxonomy/rest/v1/SubjectsTest.java @@ -102,7 +102,7 @@ public void can_create_subject_with_id() throws Exception { }; var response = testUtils.createResource("/v1/subjects", command); - assertEquals("/v1/subjects/urn:subject:1", response.getHeader("Location")); + assertEquals("/v1/nodes/urn:subject:1", response.getHeader("Location")); assertNotNull(nodeRepository.getByPublicId(command.getId().get())); } @@ -304,6 +304,6 @@ public void recursive_topics_with_relevance_are_ordered_relative_to_parent() thr var response2 = testUtils.getResource( "/v1/subjects/urn:subject:1/topics?recursive=true&relevance=urn:relevance:supplementary"); var topics2 = testUtils.getObject(NodeChildDTO[].class, response2); - assertEquals(4, topics2.length); + assertEquals(3, topics2.length); } } From 689c4a45aa97e3b202771d3a150475162abae66c Mon Sep 17 00:00:00 2001 From: Gunnar Velle Date: Mon, 14 Oct 2024 09:54:21 +0200 Subject: [PATCH 2/4] proxy topics controller --- .../java/no/ndla/taxonomy/rest/v1/Topics.java | 99 +++++++------------ 1 file changed, 38 insertions(+), 61 deletions(-) diff --git a/src/main/java/no/ndla/taxonomy/rest/v1/Topics.java b/src/main/java/no/ndla/taxonomy/rest/v1/Topics.java index 58f967df..9c07d4f8 100644 --- a/src/main/java/no/ndla/taxonomy/rest/v1/Topics.java +++ b/src/main/java/no/ndla/taxonomy/rest/v1/Topics.java @@ -12,17 +12,20 @@ import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import java.net.URI; -import java.util.*; -import java.util.stream.Collectors; +import java.util.List; +import java.util.Optional; import no.ndla.taxonomy.config.Constants; import no.ndla.taxonomy.domain.Node; import no.ndla.taxonomy.domain.NodeType; import no.ndla.taxonomy.repositories.NodeRepository; import no.ndla.taxonomy.rest.v1.commands.TopicPostPut; -import no.ndla.taxonomy.service.*; -import no.ndla.taxonomy.service.dtos.*; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.data.domain.PageRequest; +import no.ndla.taxonomy.service.ContextUpdaterService; +import no.ndla.taxonomy.service.NodeService; +import no.ndla.taxonomy.service.QualityEvaluationService; +import no.ndla.taxonomy.service.dtos.ConnectionDTO; +import no.ndla.taxonomy.service.dtos.NodeChildDTO; +import no.ndla.taxonomy.service.dtos.NodeDTO; +import no.ndla.taxonomy.service.dtos.SearchResultDTO; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; @@ -32,24 +35,18 @@ @RestController @RequestMapping(path = {"/v1/topics", "/v1/topics/"}) public class Topics extends CrudControllerWithMetadata { - private final NodeRepository nodeRepository; - private final NodeService nodeService; - private final SearchService searchService; - - @Value(value = "${new.url.separator:false}") - private boolean newUrlSeparator; + private final Nodes nodes; public Topics( + Nodes nodes, NodeRepository nodeRepository, NodeService nodeService, ContextUpdaterService contextUpdaterService, - QualityEvaluationService qualityEvaluationService, - SearchService searchService) { + QualityEvaluationService qualityEvaluationService) { super(nodeRepository, contextUpdaterService, nodeService, qualityEvaluationService); - this.nodeRepository = nodeRepository; + this.nodes = nodes; this.nodeService = nodeService; - this.searchService = searchService; } @Deprecated @@ -68,19 +65,19 @@ public List getAllTopics( Optional value, @Parameter(description = "Filter by visible") @RequestParam(value = "isVisible", required = false) Optional isVisible) { - - MetadataFilters metadataFilters = new MetadataFilters(key, value, isVisible); - return nodeService.getNodesByType( + return nodes.getAllNodes( Optional.of(List.of(NodeType.TOPIC)), - language.orElse(Constants.DefaultLanguage), - Optional.empty(), + language, contentUri, Optional.empty(), Optional.empty(), Optional.empty(), - metadataFilters, - Optional.of(false), - false, + key, + value, + isVisible, + Optional.empty(), + Optional.of(true), + true, Optional.empty(), Optional.empty()); } @@ -104,17 +101,16 @@ public SearchResultDTO searchTopics( @Parameter(description = "ContentURIs to fetch for query") @RequestParam(value = "contentUris", required = false) Optional> contentUris) { - return searchService.searchByNodeType( - query, - ids, - contentUris, + return nodes.searchNodes( language, - Optional.of(false), - false, pageSize, page, + query, + ids, + contentUris, Optional.of(List.of(NodeType.TOPIC)), - Optional.empty(), + Optional.of(true), + true, Optional.empty(), Optional.empty()); } @@ -129,26 +125,7 @@ public SearchResultDTO getTopicsPage( Optional language, @Parameter(name = "page", description = "The page to fetch") Optional page, @Parameter(name = "pageSize", description = "Size of page to fetch") Optional pageSize) { - if (page.isEmpty() || pageSize.isEmpty()) { - throw new IllegalArgumentException("Need both page and pageSize to return data"); - } - if (page.get() < 1) throw new IllegalArgumentException("page parameter must be bigger than 0"); - - var ids = nodeRepository.findIdsByTypePaginated(PageRequest.of(page.get() - 1, pageSize.get()), NodeType.TOPIC); - var results = nodeRepository.findByIds(ids.getContent()); - var contents = results.stream() - .map(node -> new NodeDTO( - Optional.empty(), - Optional.empty(), - node, - language.orElse("nb"), - Optional.empty(), - Optional.of(false), - false, - false, - newUrlSeparator)) - .collect(Collectors.toList()); - return new SearchResultDTO<>(ids.getTotalElements(), page.get(), pageSize.get(), contents); + return nodes.getNodePage(language, page, pageSize, Optional.of(NodeType.TOPIC), Optional.of(true), true, true); } @Deprecated @@ -160,7 +137,7 @@ public NodeDTO getTopic( @Parameter(description = "ISO-639-1 language code", example = "nb") @RequestParam(value = "language", required = false, defaultValue = Constants.DefaultLanguage) Optional language) { - return nodeService.getNode(id, language, Optional.empty(), Optional.empty(), Optional.of(false), false, true); + return nodes.getNode(id, Optional.empty(), Optional.empty(), Optional.of(true), true, true, language); } @Deprecated @@ -173,7 +150,7 @@ public NodeDTO getTopic( public ResponseEntity createTopic( @Parameter(name = "connection", description = "The new topic") @RequestBody @Schema(name = "TopicPOST") TopicPostPut command) { - return createEntity(new Node(NodeType.TOPIC), command); + return nodes.createEntity(new Node(NodeType.TOPIC), command); } @Deprecated @@ -190,7 +167,7 @@ public void updateTopic( @RequestBody @Schema(name = "VersionPUT") TopicPostPut command) { - updateEntity(id, command); + nodes.updateEntity(id, command); } @Deprecated @@ -207,7 +184,8 @@ public List getTopicSubTopics( @Parameter(description = "ISO-639-1 language code", example = "nb") @RequestParam(value = "language", required = false, defaultValue = Constants.DefaultLanguage) Optional language) { - return nodeService.getFilteredChildConnections(id, language.orElse(Constants.DefaultLanguage)); + return nodes.getChildren( + id, Optional.of(List.of(NodeType.TOPIC)), false, language, Optional.of(true), true, true); } @Deprecated @@ -215,7 +193,7 @@ public List getTopicSubTopics( @Operation(summary = "Gets all subjects and subtopics this topic is connected to") @Transactional(readOnly = true) public List getAllTopicConnections(@PathVariable("id") URI id) { - return nodeService.getAllConnections(id); + return nodes.getAllConnections(id); } @Deprecated @@ -227,7 +205,7 @@ public List getAllTopicConnections(@PathVariable("id") URI id) { @ResponseStatus(HttpStatus.NO_CONTENT) @Transactional public void deleteEntity(@PathVariable("id") URI id) { - nodeService.delete(id); + nodes.deleteEntity(id); } @Deprecated @@ -253,9 +231,8 @@ public List getTopicResources( @Parameter(description = "Select by relevance. If not specified, all resources will be returned.") @RequestParam(value = "relevance", required = false) Optional relevance) { - - return nodeService.getResourcesByNodeId( - topicId, resourceTypeIds, relevance, language, recursive, Optional.of(false), false, true); + return nodes.getResources( + topicId, language, Optional.of(true), true, true, recursive, resourceTypeIds, relevance); } @Deprecated @@ -270,6 +247,6 @@ public ResponseEntity makeResourcesPrimary( @Parameter(description = "If true, children are fetched recursively") @RequestParam(value = "recursive", required = false, defaultValue = "false") boolean recursive) { - return ResponseEntity.of(Optional.of(nodeService.makeAllResourcesPrimary(nodeId, recursive))); + return nodes.makeResourcesPrimary(nodeId, recursive); } } From 8cb7cdc892c7e2d9b597754ab84f667d6534041e Mon Sep 17 00:00:00 2001 From: Gunnar Velle Date: Mon, 14 Oct 2024 10:05:00 +0200 Subject: [PATCH 3/4] proxy resources controller --- .../no/ndla/taxonomy/rest/v1/Resources.java | 79 +++++++------------ 1 file changed, 28 insertions(+), 51 deletions(-) diff --git a/src/main/java/no/ndla/taxonomy/rest/v1/Resources.java b/src/main/java/no/ndla/taxonomy/rest/v1/Resources.java index e1c5056e..d66f29f7 100644 --- a/src/main/java/no/ndla/taxonomy/rest/v1/Resources.java +++ b/src/main/java/no/ndla/taxonomy/rest/v1/Resources.java @@ -14,20 +14,20 @@ import java.net.URI; import java.util.List; import java.util.Optional; -import java.util.stream.Collectors; import no.ndla.taxonomy.config.Constants; import no.ndla.taxonomy.domain.Node; import no.ndla.taxonomy.domain.NodeType; import no.ndla.taxonomy.repositories.NodeRepository; import no.ndla.taxonomy.repositories.ResourceResourceTypeRepository; import no.ndla.taxonomy.rest.v1.commands.ResourcePostPut; -import no.ndla.taxonomy.service.*; +import no.ndla.taxonomy.service.ContextUpdaterService; +import no.ndla.taxonomy.service.NodeService; +import no.ndla.taxonomy.service.QualityEvaluationService; import no.ndla.taxonomy.service.dtos.NodeDTO; import no.ndla.taxonomy.service.dtos.NodeWithParents; import no.ndla.taxonomy.service.dtos.ResourceTypeWithConnectionDTO; import no.ndla.taxonomy.service.dtos.SearchResultDTO; import org.springframework.beans.factory.annotation.Value; -import org.springframework.data.domain.PageRequest; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; @@ -37,28 +37,26 @@ @RestController @RequestMapping(path = {"/v1/resources", "/v1/resources/"}) public class Resources extends CrudControllerWithMetadata { + private final Nodes nodes; private final ResourceResourceTypeRepository resourceResourceTypeRepository; private final NodeService nodeService; - private final NodeRepository nodeRepository; - private final SearchService searchService; @Value(value = "${new.url.separator:false}") private boolean newUrlSeparator; public Resources( + Nodes nodes, NodeRepository nodeRepository, ResourceResourceTypeRepository resourceResourceTypeRepository, ContextUpdaterService contextUpdaterService, NodeService nodeService, - QualityEvaluationService qualityEvaluationService, - SearchService searchService) { + QualityEvaluationService qualityEvaluationService) { super(nodeRepository, contextUpdaterService, nodeService, qualityEvaluationService); + this.nodes = nodes; this.resourceResourceTypeRepository = resourceResourceTypeRepository; this.repository = nodeRepository; - this.nodeRepository = nodeRepository; this.nodeService = nodeService; - this.searchService = searchService; } @Override @@ -82,18 +80,19 @@ public List getAllResources( Optional value, @Parameter(description = "Filter by visible") @RequestParam(value = "isVisible", required = false) Optional isVisible) { - MetadataFilters metadataFilters = new MetadataFilters(key, value, isVisible); - return nodeService.getNodesByType( + return nodes.getAllNodes( Optional.of(List.of(NodeType.RESOURCE)), - language.orElse(Constants.DefaultLanguage), - Optional.empty(), + language, contentUri, Optional.empty(), Optional.empty(), Optional.empty(), - metadataFilters, - Optional.of(false), - false, + key, + value, + isVisible, + Optional.empty(), + Optional.of(true), + true, Optional.empty(), Optional.empty()); } @@ -117,17 +116,16 @@ public SearchResultDTO searchResources( @Parameter(description = "ContentURIs to fetch for query") @RequestParam(value = "contentUris", required = false) Optional> contentUris) { - return searchService.searchByNodeType( - query, - ids, - contentUris, + return nodes.searchNodes( language, - Optional.of(false), - false, pageSize, page, + query, + ids, + contentUris, Optional.of(List.of(NodeType.RESOURCE)), - Optional.empty(), + Optional.of(true), + true, Optional.empty(), Optional.empty()); } @@ -142,27 +140,8 @@ public SearchResultDTO getResourcePage( Optional language, @Parameter(name = "page", description = "The page to fetch") Optional page, @Parameter(name = "pageSize", description = "Size of page to fetch") Optional pageSize) { - if (page.isEmpty() || pageSize.isEmpty()) { - throw new IllegalArgumentException("Need both page and pageSize to return data"); - } - if (page.get() < 1) throw new IllegalArgumentException("page parameter must be bigger than 0"); - - var pageRequest = PageRequest.of(page.get() - 1, pageSize.get()); - var ids = nodeRepository.findIdsByTypePaginated(pageRequest, NodeType.RESOURCE); - var results = nodeRepository.findByIds(ids.getContent()); - var contents = results.stream() - .map(node -> new NodeDTO( - Optional.empty(), - Optional.empty(), - node, - language.orElse("nb"), - Optional.empty(), - Optional.of(false), - false, - false, - newUrlSeparator)) - .collect(Collectors.toList()); - return new SearchResultDTO<>(ids.getTotalElements(), page.get(), pageSize.get(), contents); + return nodes.getNodePage( + language, page, pageSize, Optional.of(NodeType.RESOURCE), Optional.of(true), true, true); } @Deprecated @@ -174,7 +153,7 @@ public NodeDTO getResource( @Parameter(description = "ISO-639-1 language code", example = "nb") @RequestParam(value = "language", required = false, defaultValue = Constants.DefaultLanguage) Optional language) { - return nodeService.getNode(id, language, Optional.empty(), Optional.empty(), Optional.of(false), false, true); + return nodes.getNode(id, Optional.empty(), Optional.empty(), Optional.of(true), true, true, language); } @Deprecated @@ -193,7 +172,7 @@ public void updateResource( @RequestBody @Schema(name = "ResourcePOST") ResourcePostPut command) { - updateEntity(id, command); + nodes.updateEntity(id, command); } @Deprecated @@ -206,7 +185,7 @@ public void updateResource( public ResponseEntity createResource( @Parameter(name = "resource", description = "the new resource") @RequestBody @Schema(name = "ResourcePUT") ResourcePostPut command) { - return createEntity(new Node(NodeType.RESOURCE), command); + return nodes.createEntity(new Node(NodeType.RESOURCE), command); } @Deprecated @@ -254,9 +233,7 @@ public NodeWithParents getResourceFull( @Parameter(description = "ISO-639-1 language code", example = "nb") @RequestParam(value = "language", required = false, defaultValue = Constants.DefaultLanguage) Optional language) { - var node = nodeService.getNode(id); - return new NodeWithParents( - node, language.orElse(Constants.DefaultLanguage), Optional.of(false), newUrlSeparator); + return nodes.getNodeFull(id, language, Optional.of(true)); } @Deprecated @@ -268,6 +245,6 @@ public NodeWithParents getResourceFull( @ResponseStatus(HttpStatus.NO_CONTENT) @Transactional public void deleteEntity(@PathVariable("id") URI id) { - nodeService.delete(id); + nodes.deleteEntity(id); } } From a52336b875b5e4ebc9b39ec65b2816e98ba78147 Mon Sep 17 00:00:00 2001 From: Gunnar Velle Date: Mon, 14 Oct 2024 10:09:26 +0200 Subject: [PATCH 4/4] proxy translations controllers --- .../taxonomy/rest/v1/NodeTranslations.java | 13 ++--- .../rest/v1/ResourceTranslations.java | 45 +++--------------- .../taxonomy/rest/v1/SubjectTranslations.java | 47 +++---------------- .../taxonomy/rest/v1/TopicTranslations.java | 46 +++--------------- 4 files changed, 26 insertions(+), 125 deletions(-) diff --git a/src/main/java/no/ndla/taxonomy/rest/v1/NodeTranslations.java b/src/main/java/no/ndla/taxonomy/rest/v1/NodeTranslations.java index c556d2e3..bbc4162d 100644 --- a/src/main/java/no/ndla/taxonomy/rest/v1/NodeTranslations.java +++ b/src/main/java/no/ndla/taxonomy/rest/v1/NodeTranslations.java @@ -10,10 +10,6 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.security.SecurityRequirement; -import jakarta.persistence.EntityManager; -import java.net.URI; -import java.util.ArrayList; -import java.util.List; import no.ndla.taxonomy.domain.Node; import no.ndla.taxonomy.domain.exceptions.NotFoundException; import no.ndla.taxonomy.repositories.NodeRepository; @@ -24,17 +20,18 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.*; +import java.net.URI; +import java.util.ArrayList; +import java.util.List; + @RestController @RequestMapping(path = {"/v1/nodes/{id}/translations", "/v1/nodes/{id}/translations/"}) public class NodeTranslations { private final NodeRepository nodeRepository; - private final EntityManager entityManager; - - public NodeTranslations(NodeRepository nodeRepository, EntityManager entityManager) { + public NodeTranslations(NodeRepository nodeRepository) { this.nodeRepository = nodeRepository; - this.entityManager = entityManager; } @GetMapping diff --git a/src/main/java/no/ndla/taxonomy/rest/v1/ResourceTranslations.java b/src/main/java/no/ndla/taxonomy/rest/v1/ResourceTranslations.java index 3b8b3c75..c9e9f663 100644 --- a/src/main/java/no/ndla/taxonomy/rest/v1/ResourceTranslations.java +++ b/src/main/java/no/ndla/taxonomy/rest/v1/ResourceTranslations.java @@ -10,12 +10,8 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.security.SecurityRequirement; -import jakarta.persistence.EntityManager; import java.net.URI; -import java.util.ArrayList; import java.util.List; -import no.ndla.taxonomy.domain.exceptions.NotFoundException; -import no.ndla.taxonomy.repositories.NodeRepository; import no.ndla.taxonomy.rest.v1.dtos.TranslationPUT; import no.ndla.taxonomy.service.dtos.TranslationDTO; import org.springframework.http.HttpStatus; @@ -27,13 +23,10 @@ @RequestMapping(path = {"/v1/resources/{id}/translations", "/v1/resources/{id}/translations/"}) public class ResourceTranslations { - private final NodeRepository nodeRepository; + private final NodeTranslations nodeTranslations; - private final EntityManager entityManager; - - public ResourceTranslations(NodeRepository resourceRepository, EntityManager entityManager) { - this.nodeRepository = resourceRepository; - this.entityManager = entityManager; + public ResourceTranslations(NodeTranslations nodeTranslations) { + this.nodeTranslations = nodeTranslations; } @Deprecated @@ -41,16 +34,7 @@ public ResourceTranslations(NodeRepository resourceRepository, EntityManager ent @Operation(summary = "Gets all relevanceTranslations for a single resource") @Transactional(readOnly = true) public List getAllResourceTranslations(@PathVariable("id") URI id) { - var resource = nodeRepository.getByPublicId(id); - List result = new ArrayList<>(); - resource.getTranslations() - .forEach(t -> result.add(new TranslationDTO() { - { - name = t.getName(); - language = t.getLanguageCode(); - } - })); - return result; + return nodeTranslations.getAllNodeTranslations(id); } @Deprecated @@ -62,16 +46,7 @@ public TranslationDTO getResourceTranslation( @Parameter(description = "ISO-639-1 language code", example = "nb", required = true) @PathVariable("language") String language) { - var resource = nodeRepository.getByPublicId(id); - var translation = resource.getTranslation(language) - .orElseThrow(() -> - new NotFoundException("translation with language code " + language + " for resource", id)); - return new TranslationDTO() { - { - name = translation.getName(); - language = translation.getLanguageCode(); - } - }; + return nodeTranslations.getNodeTranslation(id, language); } @Deprecated @@ -89,9 +64,7 @@ public void createUpdateResourceTranslation( String language, @Parameter(name = "resource", description = "The new or updated translation") @RequestBody TranslationPUT command) { - var resource = nodeRepository.getByPublicId(id); - resource.addTranslation(command.name, language); - entityManager.persist(resource); + nodeTranslations.createUpdateNodeTranslation(id, language, command); } @Deprecated @@ -107,10 +80,6 @@ public void deleteResourceTranslation( @Parameter(description = "ISO-639-1 language code", example = "nb", required = true) @PathVariable("language") String language) { - final var resource = nodeRepository.getByPublicId(id); - resource.getTranslation(language).ifPresent((translation) -> { - resource.removeTranslation(language); - nodeRepository.save(resource); - }); + nodeTranslations.deleteNodeTranslation(id, language); } } diff --git a/src/main/java/no/ndla/taxonomy/rest/v1/SubjectTranslations.java b/src/main/java/no/ndla/taxonomy/rest/v1/SubjectTranslations.java index be225764..4442ba7b 100644 --- a/src/main/java/no/ndla/taxonomy/rest/v1/SubjectTranslations.java +++ b/src/main/java/no/ndla/taxonomy/rest/v1/SubjectTranslations.java @@ -10,13 +10,8 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.security.SecurityRequirement; -import jakarta.persistence.EntityManager; import java.net.URI; -import java.util.ArrayList; import java.util.List; -import no.ndla.taxonomy.domain.Node; -import no.ndla.taxonomy.domain.exceptions.NotFoundException; -import no.ndla.taxonomy.repositories.NodeRepository; import no.ndla.taxonomy.rest.v1.dtos.TranslationPUT; import no.ndla.taxonomy.service.dtos.TranslationDTO; import org.springframework.http.HttpStatus; @@ -27,13 +22,10 @@ @RestController @RequestMapping(path = {"/v1/subjects/{id}/translations", "/v1/subjects/{id}/translations/"}) public class SubjectTranslations { - private final NodeRepository nodeRepository; + private final NodeTranslations nodeTranslations; - private final EntityManager entityManager; - - public SubjectTranslations(NodeRepository nodeRepository, EntityManager entityManager) { - this.nodeRepository = nodeRepository; - this.entityManager = entityManager; + public SubjectTranslations(NodeTranslations nodeTranslations) { + this.nodeTranslations = nodeTranslations; } @Deprecated @@ -41,16 +33,7 @@ public SubjectTranslations(NodeRepository nodeRepository, EntityManager entityMa @Operation(summary = "Gets all relevanceTranslations for a single subject") @Transactional(readOnly = true) public List getAllSubjectTranslations(@PathVariable("id") URI id) { - Node subject = nodeRepository.getByPublicId(id); - List result = new ArrayList<>(); - subject.getTranslations() - .forEach(t -> result.add(new TranslationDTO() { - { - name = t.getName(); - language = t.getLanguageCode(); - } - })); - return result; + return nodeTranslations.getAllNodeTranslations(id); } @Deprecated @@ -62,17 +45,7 @@ public TranslationDTO getSubjectTranslation( @Parameter(description = "ISO-639-1 language code", example = "nb", required = true) @PathVariable("language") String language) { - Node subject = nodeRepository.getByPublicId(id); - var translation = subject.getTranslation(language) - .orElseThrow( - () -> new NotFoundException("translation with language code " + language + " for subject", id)); - - return new TranslationDTO() { - { - name = translation.getName(); - language = translation.getLanguageCode(); - } - }; + return nodeTranslations.getNodeTranslation(id, language); } @Deprecated @@ -88,11 +61,7 @@ public void deleteSubjectTranslation( @Parameter(description = "ISO-639-1 language code", example = "nb", required = true) @PathVariable("language") String language) { - Node subject = nodeRepository.getByPublicId(id); - subject.getTranslation(language).ifPresent((translation) -> { - subject.removeTranslation(language); - entityManager.persist(subject); - }); + nodeTranslations.deleteNodeTranslation(id, language); } @Deprecated @@ -110,8 +79,6 @@ public void createUpdateSubjectTranslation( String language, @Parameter(name = "subject", description = "The new or updated translation") @RequestBody TranslationPUT command) { - Node subject = nodeRepository.getByPublicId(id); - subject.addTranslation(command.name, language); - entityManager.persist(subject); + nodeTranslations.createUpdateNodeTranslation(id, language, command); } } diff --git a/src/main/java/no/ndla/taxonomy/rest/v1/TopicTranslations.java b/src/main/java/no/ndla/taxonomy/rest/v1/TopicTranslations.java index 7a88d7d8..5fddbf81 100644 --- a/src/main/java/no/ndla/taxonomy/rest/v1/TopicTranslations.java +++ b/src/main/java/no/ndla/taxonomy/rest/v1/TopicTranslations.java @@ -10,13 +10,8 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.security.SecurityRequirement; -import jakarta.persistence.EntityManager; import java.net.URI; -import java.util.ArrayList; import java.util.List; -import no.ndla.taxonomy.domain.Node; -import no.ndla.taxonomy.domain.exceptions.NotFoundException; -import no.ndla.taxonomy.repositories.NodeRepository; import no.ndla.taxonomy.rest.v1.dtos.TranslationPUT; import no.ndla.taxonomy.service.dtos.TranslationDTO; import org.springframework.http.HttpStatus; @@ -28,13 +23,10 @@ @RequestMapping(path = {"/v1/topics/{id}/translations", "/v1/topics/{id}/translations/"}) public class TopicTranslations { - private final NodeRepository nodeRepository; + private final NodeTranslations nodeTranslations; - private final EntityManager entityManager; - - public TopicTranslations(NodeRepository nodeRepository, EntityManager entityManager) { - this.nodeRepository = nodeRepository; - this.entityManager = entityManager; + public TopicTranslations(NodeTranslations nodeTranslations) { + this.nodeTranslations = nodeTranslations; } @Deprecated @@ -42,16 +34,7 @@ public TopicTranslations(NodeRepository nodeRepository, EntityManager entityMana @Operation(summary = "Gets all relevanceTranslations for a single topic") @Transactional(readOnly = true) public List getAllTopicTranslations(@PathVariable("id") URI id) { - Node topic = nodeRepository.getByPublicId(id); - List result = new ArrayList<>(); - topic.getTranslations() - .forEach(t -> result.add(new TranslationDTO() { - { - name = t.getName(); - language = t.getLanguageCode(); - } - })); - return result; + return nodeTranslations.getAllNodeTranslations(id); } @Deprecated @@ -63,16 +46,7 @@ public TranslationDTO getTopicTranslation( @Parameter(description = "ISO-639-1 language code", example = "nb", required = true) @PathVariable("language") String language) { - Node topic = nodeRepository.getByPublicId(id); - var translation = topic.getTranslation(language) - .orElseThrow( - () -> new NotFoundException("translation with language code " + language + " for topic", id)); - return new TranslationDTO() { - { - name = translation.getName(); - language = translation.getLanguageCode(); - } - }; + return nodeTranslations.getNodeTranslation(id, language); } @Deprecated @@ -90,9 +64,7 @@ public void createUpdateTopicTranslation( String language, @Parameter(name = "topic", description = "The new or updated translation") @RequestBody TranslationPUT command) { - var topic = nodeRepository.getByPublicId(id); - topic.addTranslation(command.name, language); - entityManager.persist(topic); + nodeTranslations.createUpdateNodeTranslation(id, language, command); } @Deprecated @@ -108,10 +80,6 @@ public void deleteTopicTranslation( @Parameter(description = "ISO-639-1 language code", example = "nb", required = true) @PathVariable("language") String language) { - Node topic = nodeRepository.getByPublicId(id); - topic.getTranslation(language).ifPresent(topicTranslation -> { - topic.removeTranslation(language); - entityManager.persist(topic); - }); + nodeTranslations.deleteNodeTranslation(id, language); } }