From 0e43651ad5951dbcf3859d3b1fc83953e86a8eb8 Mon Sep 17 00:00:00 2001 From: BartChris Date: Mon, 19 Aug 2024 16:28:31 +0200 Subject: [PATCH 1/4] Speed up display of parent processes --- .../search/SearchRestClient.java | 38 +++++++++++++ .../data/elasticsearch/search/Searcher.java | 12 +++++ .../forms/dataeditor/StructurePanel.java | 54 ++++++++++++------- .../services/data/ProcessService.java | 4 ++ .../services/data/base/SearchService.java | 24 +++++++++ .../forms/dataeditor/StructurePanelTest.java | 9 +++- 6 files changed, 121 insertions(+), 20 deletions(-) diff --git a/Kitodo-DataManagement/src/main/java/org/kitodo/data/elasticsearch/search/SearchRestClient.java b/Kitodo-DataManagement/src/main/java/org/kitodo/data/elasticsearch/search/SearchRestClient.java index 27d908ab697..23029ccbf68 100644 --- a/Kitodo-DataManagement/src/main/java/org/kitodo/data/elasticsearch/search/SearchRestClient.java +++ b/Kitodo-DataManagement/src/main/java/org/kitodo/data/elasticsearch/search/SearchRestClient.java @@ -14,6 +14,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Collections; +import java.util.List; import java.util.Map; import java.util.Objects; @@ -25,6 +26,9 @@ import org.apache.http.util.EntityUtils; import org.elasticsearch.action.get.GetRequest; import org.elasticsearch.action.get.GetResponse; +import org.elasticsearch.action.get.MultiGetItemResponse; +import org.elasticsearch.action.get.MultiGetRequest; +import org.elasticsearch.action.get.MultiGetResponse; import org.elasticsearch.action.search.SearchRequest; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.client.Request; @@ -193,6 +197,40 @@ SearchHits getDocument(String type, QueryBuilder query, SortBuilder sort, Intege } } + /** + * Get document list for given ids. + * + * @param type + * for which request is performed + * @param ids + * of searched documents + * @return a list of documents, each represented as a map with document ID under the "id" key. + */ + public List> getDocuments(String type, List ids) throws CustomResponseException, DataException { + List> documents = new ArrayList<>(); + + try { + // Create a MultiGetRequest to fetch multiple documents + MultiGetRequest multiGetRequest = new MultiGetRequest(); + for (Integer id : ids) { + multiGetRequest.add(new MultiGetRequest.Item(this.indexBase + "_" + type, String.valueOf(id))); + } + MultiGetResponse multiGetResponse = highLevelClient.mget(multiGetRequest, RequestOptions.DEFAULT); + for (MultiGetItemResponse itemResponse : multiGetResponse.getResponses()) { + if (!itemResponse.isFailed() && itemResponse.getResponse().isExists()) { + Map document = itemResponse.getResponse().getSourceAsMap(); + document.put("id", itemResponse.getResponse().getId()); + documents.add(document); + } + } + } catch (ResponseException e) { + handleResponseException(e); + } catch (IOException e) { + throw new DataException(e); + } + return documents; + } + private String performRequest(String type, HttpEntity entity, String httpMethod, String urlRequest) throws CustomResponseException, DataException { String output = ""; diff --git a/Kitodo-DataManagement/src/main/java/org/kitodo/data/elasticsearch/search/Searcher.java b/Kitodo-DataManagement/src/main/java/org/kitodo/data/elasticsearch/search/Searcher.java index 002f93b5efc..f57949eaa13 100644 --- a/Kitodo-DataManagement/src/main/java/org/kitodo/data/elasticsearch/search/Searcher.java +++ b/Kitodo-DataManagement/src/main/java/org/kitodo/data/elasticsearch/search/Searcher.java @@ -104,6 +104,18 @@ public Aggregations aggregateDocuments(QueryBuilder query, AggregationBuilder ag return restClient.aggregateDocuments(this.type, query, aggregation); } + /** + * Get documents by id. + * + * @param ids + * of searched document as List + * @return JSONObject + */ + public List> getDocuments(List ids) throws CustomResponseException, DataException { + SearchRestClient restClient = initiateRestClient(); + return restClient.getDocuments(this.type,ids); + } + /** * Find document by id. * diff --git a/Kitodo/src/main/java/org/kitodo/production/forms/dataeditor/StructurePanel.java b/Kitodo/src/main/java/org/kitodo/production/forms/dataeditor/StructurePanel.java index 74887942d25..4e9436b2cd2 100644 --- a/Kitodo/src/main/java/org/kitodo/production/forms/dataeditor/StructurePanel.java +++ b/Kitodo/src/main/java/org/kitodo/production/forms/dataeditor/StructurePanel.java @@ -558,10 +558,28 @@ private DefaultTreeNode buildStructureTree() { invisibleRootNode.setExpanded(true); invisibleRootNode.setType(STRUCTURE_NODE_TYPE); addParentLinksRecursive(dataEditor.getProcess(), invisibleRootNode); - buildStructureTreeRecursively(structure, invisibleRootNode); + List processIds = getAllLinkedProcessIds(structure); + Map processTypeMap = processIds.isEmpty() ? Collections.emptyMap() : fetchProcessTypes(processIds); + buildStructureTreeRecursively(structure, invisibleRootNode, processTypeMap); return invisibleRootNode; } + private List getAllLinkedProcessIds(LogicalDivision structure) { + return structure.getAllChildren().stream() + .filter(division -> division.getLink() != null) + .map(division -> ServiceManager.getProcessService().processIdFromUri(division.getLink().getUri())) + .collect(Collectors.toList()); + } + + private Map fetchProcessTypes(List processIds) { + try { + return ServiceManager.getProcessService().getIdBaseTypeMap(processIds); + } catch (DataException e) { + Helper.setErrorMessage("metadataReadError", e.getMessage(), logger, e); + return Collections.emptyMap(); + } + } + /** * Constructs a page range string by combining the labels of the first and last view * of the provided logical division. @@ -585,7 +603,7 @@ private String buildPageRangeFromLogicalDivision(LogicalDivision structure) { * @param structure the logical division * @return the StructureTreeNode instance */ - private StructureTreeNode buildStructureTreeNode(LogicalDivision structure) { + private StructureTreeNode buildStructureTreeNode(LogicalDivision structure, Map idTypeMap) { StructureTreeNode node; if (Objects.isNull(structure.getLink())) { StructuralElementViewInterface divisionView = dataEditor.getRulesetManagement().getStructuralElementView( @@ -596,19 +614,17 @@ private StructureTreeNode buildStructureTreeNode(LogicalDivision structure) { node = new StructureTreeNode(label, pageRange, undefined, false, structure); } else { node = new StructureTreeNode(structure.getLink().getUri().toString(), null, true, true, structure); + Map viewCache = new HashMap<>(); for (Process child : dataEditor.getCurrentChildren()) { - try { - String type = ServiceManager.getProcessService().getBaseType(child.getId()); - if (child.getId() == ServiceManager.getProcessService() - .processIdFromUri(structure.getLink().getUri())) { - StructuralElementViewInterface view = dataEditor.getRulesetManagement().getStructuralElementView( - type, dataEditor.getAcquisitionStage(), dataEditor.getPriorityList()); - node = new StructureTreeNode("[" + child.getId() + "] " + view.getLabel() + " - " - + child.getTitle(), null, view.isUndefined(), true, structure); - } - } catch (DataException e) { - Helper.setErrorMessage("metadataReadError", e.getMessage(), logger, e); - node = new StructureTreeNode(child.getTitle(), null, true, true, child); + if (child.getId() == ServiceManager.getProcessService().processIdFromUri(structure.getLink().getUri())) { + String type = idTypeMap.get(child.getId()); + // Retrieve the view from cache if it exists, otherwise compute and cache it + StructuralElementViewInterface view = viewCache.computeIfAbsent(type, key -> + dataEditor.getRulesetManagement().getStructuralElementView( + key, dataEditor.getAcquisitionStage(), dataEditor.getPriorityList()) + ); + node = new StructureTreeNode("[" + child.getId() + "] " + view.getLabel() + " - " + + child.getTitle(), null, view.isUndefined(), true, structure); } } } @@ -620,10 +636,12 @@ private StructureTreeNode buildStructureTreeNode(LogicalDivision structure) { * * @param structure the current logical structure * @param result the current corresponding primefaces tree node + * @param processTypeMap the mapping of process id to basetype * @return a collection of views that contains all views of the full sub-tree */ - private Collection buildStructureTreeRecursively(LogicalDivision structure, TreeNode result) { - StructureTreeNode node = buildStructureTreeNode(structure); + private Collection buildStructureTreeRecursively(LogicalDivision structure, TreeNode result, Map processTypeMap) { + StructureTreeNode node = buildStructureTreeNode(structure, processTypeMap); /* * Creating the tree node by handing over the parent node automatically * appends it to the parent as a child. That’s the logic of the JSF @@ -637,7 +655,7 @@ private Collection buildStructureTreeRecursively(LogicalDivision structure Set viewsShowingOnAChild = new HashSet<>(); if (!this.logicalStructureTreeContainsMedia()) { for (LogicalDivision child : structure.getChildren()) { - viewsShowingOnAChild.addAll(buildStructureTreeRecursively(child, parent)); + viewsShowingOnAChild.addAll(buildStructureTreeRecursively(child, parent, processTypeMap)); } } else { // iterate through children and views ordered by the ORDER attribute @@ -645,7 +663,7 @@ private Collection buildStructureTreeRecursively(LogicalDivision structure for (Pair pair : merged) { if (Objects.nonNull(pair.getRight())) { // add child and their views - viewsShowingOnAChild.addAll(buildStructureTreeRecursively(pair.getRight(), parent)); + viewsShowingOnAChild.addAll(buildStructureTreeRecursively(pair.getRight(), parent, processTypeMap)); } else if (!viewsShowingOnAChild.contains(pair.getLeft())) { // add views of current logical division as leaf nodes DefaultTreeNode viewNode = addTreeNode(buildViewLabel(pair.getLeft()), false, false, pair.getLeft(), parent); diff --git a/Kitodo/src/main/java/org/kitodo/production/services/data/ProcessService.java b/Kitodo/src/main/java/org/kitodo/production/services/data/ProcessService.java index 5ecc4467811..a47f4705e2e 100644 --- a/Kitodo/src/main/java/org/kitodo/production/services/data/ProcessService.java +++ b/Kitodo/src/main/java/org/kitodo/production/services/data/ProcessService.java @@ -1730,6 +1730,10 @@ public String getBaseType(int processId) throws DataException { return ""; } + public Map getIdBaseTypeMap(List processIds) throws DataException { + return getIdTypeMap(processIds); + } + /** * Filter for correction / solution messages. * diff --git a/Kitodo/src/main/java/org/kitodo/production/services/data/base/SearchService.java b/Kitodo/src/main/java/org/kitodo/production/services/data/base/SearchService.java index 0758af802dc..d903003ad83 100644 --- a/Kitodo/src/main/java/org/kitodo/production/services/data/base/SearchService.java +++ b/Kitodo/src/main/java/org/kitodo/production/services/data/base/SearchService.java @@ -20,6 +20,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Date; +import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -458,6 +459,29 @@ public S findById(Integer id, boolean related) throws DataException { } } + /** + * Retrieves documents for the given list of IDs, extracts the "id" and "baseType" fields, + * and maps each ID to its corresponding base type. + * + * @param ids + * list of document IDs to retrieve and process. + * @return a map where the keys are document IDs and the values are their associated base types. + */ + public Map getIdTypeMap(List ids) throws DataException { + try { + List> documents = searcher.getDocuments(ids); + Map idToBaseTypeMap = new HashMap<>(); + for (Map document : documents) { + Integer id = Integer.parseInt((String) document.get("id")); + String baseType = (String) document.get("baseType"); + idToBaseTypeMap.put(id, baseType); + } + return idToBaseTypeMap; + } catch (CustomResponseException e) { + throw new DataException(e); + } + } + /** * Find list of DTO objects by query. * diff --git a/Kitodo/src/test/java/org/kitodo/production/forms/dataeditor/StructurePanelTest.java b/Kitodo/src/test/java/org/kitodo/production/forms/dataeditor/StructurePanelTest.java index 5f896815f2a..52e698c3f18 100644 --- a/Kitodo/src/test/java/org/kitodo/production/forms/dataeditor/StructurePanelTest.java +++ b/Kitodo/src/test/java/org/kitodo/production/forms/dataeditor/StructurePanelTest.java @@ -17,6 +17,8 @@ import java.lang.reflect.Field; import java.lang.reflect.Method; import java.net.URI; +import java.util.HashMap; +import java.util.Map; import org.junit.jupiter.api.Test; import org.kitodo.DummyRulesetManagement; @@ -25,6 +27,7 @@ import org.kitodo.data.database.beans.Process; import org.kitodo.data.database.beans.Template; import org.kitodo.data.database.beans.Workflow; +import org.kitodo.production.services.ServiceManager; import org.primefaces.model.DefaultTreeNode; import org.primefaces.model.TreeNode; @@ -47,12 +50,14 @@ public void testBuildStructureTreeRecursively() throws Exception { LinkedMetsResource link = new LinkedMetsResource(); link.setUri(URI.create("database://?process.id=42")); structure.setLink(link); + Map processTypeMap = new HashMap<>(); + processTypeMap.put(ServiceManager.getProcessService().processIdFromUri(link.getUri()), "Monograph"); TreeNode result = new DefaultTreeNode(); Method buildStructureTreeRecursively = StructurePanel.class.getDeclaredMethod("buildStructureTreeRecursively", - LogicalDivision.class, TreeNode.class); + LogicalDivision.class, TreeNode.class, Map.class); buildStructureTreeRecursively.setAccessible(true); - buildStructureTreeRecursively.invoke(underTest, structure, result); + buildStructureTreeRecursively.invoke(underTest, structure, result, processTypeMap); assertTrue(((StructureTreeNode) result.getChildren().get(0).getData()).isLinked()); } From 1f6a523d69c7cee14654b41646a950c084bd0c9d Mon Sep 17 00:00:00 2001 From: BartChris Date: Thu, 29 Aug 2024 18:19:13 +0200 Subject: [PATCH 2/4] Simplify and optimize Elasticsearch retrieval by fetching only required fields --- .../search/SearchRestClient.java | 34 +++++++++++-------- .../data/elasticsearch/search/Searcher.java | 11 +++--- .../services/data/ProcessService.java | 2 +- .../services/data/base/SearchService.java | 14 ++------ 4 files changed, 29 insertions(+), 32 deletions(-) diff --git a/Kitodo-DataManagement/src/main/java/org/kitodo/data/elasticsearch/search/SearchRestClient.java b/Kitodo-DataManagement/src/main/java/org/kitodo/data/elasticsearch/search/SearchRestClient.java index 23029ccbf68..4893747dc03 100644 --- a/Kitodo-DataManagement/src/main/java/org/kitodo/data/elasticsearch/search/SearchRestClient.java +++ b/Kitodo-DataManagement/src/main/java/org/kitodo/data/elasticsearch/search/SearchRestClient.java @@ -14,6 +14,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; @@ -40,6 +41,7 @@ import org.elasticsearch.search.aggregations.AggregationBuilder; import org.elasticsearch.search.aggregations.Aggregations; import org.elasticsearch.search.builder.SearchSourceBuilder; +import org.elasticsearch.search.fetch.subphase.FetchSourceContext; import org.elasticsearch.search.sort.SortBuilder; import org.kitodo.data.elasticsearch.KitodoRestClient; import org.kitodo.data.elasticsearch.exceptions.CustomResponseException; @@ -198,37 +200,39 @@ SearchHits getDocument(String type, QueryBuilder query, SortBuilder sort, Intege } /** - * Get document list for given ids. + * Retrieves a map of document IDs to their corresponding base type for the given list of IDs. * - * @param type - * for which request is performed - * @param ids - * of searched documents - * @return a list of documents, each represented as a map with document ID under the "id" key. + * @param type the type of documents being requested, used to determine the index. + * @param ids the list of document IDs to search for. + * @return a map where each key is a document ID and the value is the corresponding base type of the document. */ - public List> getDocuments(String type, List ids) throws CustomResponseException, DataException { - List> documents = new ArrayList<>(); + public Map fetchIdToBaseTypeMap(String type, List ids) throws CustomResponseException, DataException { + Map idToBaseTypeMap = new HashMap<>(); try { - // Create a MultiGetRequest to fetch multiple documents + // Create a MultiGetRequest to fetch multiple documents with only baseType field MultiGetRequest multiGetRequest = new MultiGetRequest(); for (Integer id : ids) { - multiGetRequest.add(new MultiGetRequest.Item(this.indexBase + "_" + type, String.valueOf(id))); + MultiGetRequest.Item item = new MultiGetRequest.Item(this.indexBase + "_" + type, String.valueOf(id)); + // Only fetch baseType field + item.fetchSourceContext(new FetchSourceContext(true, new String[]{"baseType"}, null)); + multiGetRequest.add(item); } MultiGetResponse multiGetResponse = highLevelClient.mget(multiGetRequest, RequestOptions.DEFAULT); for (MultiGetItemResponse itemResponse : multiGetResponse.getResponses()) { if (!itemResponse.isFailed() && itemResponse.getResponse().isExists()) { - Map document = itemResponse.getResponse().getSourceAsMap(); - document.put("id", itemResponse.getResponse().getId()); - documents.add(document); + String baseType = (String) itemResponse.getResponse().getSourceAsMap().get("baseType"); + Integer id = Integer.parseInt(itemResponse.getResponse().getId()); + idToBaseTypeMap.put(id, baseType); } } } catch (ResponseException e) { handleResponseException(e); - } catch (IOException e) { + } catch (IOException | NumberFormatException e) { throw new DataException(e); } - return documents; + + return idToBaseTypeMap; } private String performRequest(String type, HttpEntity entity, String httpMethod, String urlRequest) diff --git a/Kitodo-DataManagement/src/main/java/org/kitodo/data/elasticsearch/search/Searcher.java b/Kitodo-DataManagement/src/main/java/org/kitodo/data/elasticsearch/search/Searcher.java index f57949eaa13..c3e99897a31 100644 --- a/Kitodo-DataManagement/src/main/java/org/kitodo/data/elasticsearch/search/Searcher.java +++ b/Kitodo-DataManagement/src/main/java/org/kitodo/data/elasticsearch/search/Searcher.java @@ -105,15 +105,16 @@ public Aggregations aggregateDocuments(QueryBuilder query, AggregationBuilder ag } /** - * Get documents by id. + * Retrieves a mapping of document IDs to their corresponding base type for the given list of IDs. + * Delegates to the `SearchRestClient`. * * @param ids - * of searched document as List - * @return JSONObject + * the list of document IDs to search for. + * @return a map where each key is a document ID and the value is the corresponding base type of the document. */ - public List> getDocuments(List ids) throws CustomResponseException, DataException { + public Map fetchIdToBaseTypeMap(List ids) throws CustomResponseException, DataException { SearchRestClient restClient = initiateRestClient(); - return restClient.getDocuments(this.type,ids); + return restClient.fetchIdToBaseTypeMap(this.type,ids); } /** diff --git a/Kitodo/src/main/java/org/kitodo/production/services/data/ProcessService.java b/Kitodo/src/main/java/org/kitodo/production/services/data/ProcessService.java index a47f4705e2e..bcd17d5e3f1 100644 --- a/Kitodo/src/main/java/org/kitodo/production/services/data/ProcessService.java +++ b/Kitodo/src/main/java/org/kitodo/production/services/data/ProcessService.java @@ -1731,7 +1731,7 @@ public String getBaseType(int processId) throws DataException { } public Map getIdBaseTypeMap(List processIds) throws DataException { - return getIdTypeMap(processIds); + return fetchIdToBaseTypeMap(processIds); } /** diff --git a/Kitodo/src/main/java/org/kitodo/production/services/data/base/SearchService.java b/Kitodo/src/main/java/org/kitodo/production/services/data/base/SearchService.java index d903003ad83..23a9a09bf00 100644 --- a/Kitodo/src/main/java/org/kitodo/production/services/data/base/SearchService.java +++ b/Kitodo/src/main/java/org/kitodo/production/services/data/base/SearchService.java @@ -460,23 +460,15 @@ public S findById(Integer id, boolean related) throws DataException { } /** - * Retrieves documents for the given list of IDs, extracts the "id" and "baseType" fields, - * and maps each ID to its corresponding base type. + * Retrieves a mapping of document IDs to their corresponding base types for the given list of IDs. * * @param ids * list of document IDs to retrieve and process. * @return a map where the keys are document IDs and the values are their associated base types. */ - public Map getIdTypeMap(List ids) throws DataException { + public Map fetchIdToBaseTypeMap(List ids) throws DataException { try { - List> documents = searcher.getDocuments(ids); - Map idToBaseTypeMap = new HashMap<>(); - for (Map document : documents) { - Integer id = Integer.parseInt((String) document.get("id")); - String baseType = (String) document.get("baseType"); - idToBaseTypeMap.put(id, baseType); - } - return idToBaseTypeMap; + return searcher.fetchIdToBaseTypeMap(ids); } catch (CustomResponseException e) { throw new DataException(e); } From 292c903e5c43f93ece8b58050d6e9aeda2fbbaaf Mon Sep 17 00:00:00 2001 From: BartChris Date: Thu, 29 Aug 2024 19:43:03 +0200 Subject: [PATCH 3/4] Optimize Viewcache --- .../forms/dataeditor/StructurePanel.java | 22 +++++++++++-------- .../forms/dataeditor/StructurePanelTest.java | 6 +++-- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/Kitodo/src/main/java/org/kitodo/production/forms/dataeditor/StructurePanel.java b/Kitodo/src/main/java/org/kitodo/production/forms/dataeditor/StructurePanel.java index 4e9436b2cd2..680c7084812 100644 --- a/Kitodo/src/main/java/org/kitodo/production/forms/dataeditor/StructurePanel.java +++ b/Kitodo/src/main/java/org/kitodo/production/forms/dataeditor/StructurePanel.java @@ -560,7 +560,8 @@ private DefaultTreeNode buildStructureTree() { addParentLinksRecursive(dataEditor.getProcess(), invisibleRootNode); List processIds = getAllLinkedProcessIds(structure); Map processTypeMap = processIds.isEmpty() ? Collections.emptyMap() : fetchProcessTypes(processIds); - buildStructureTreeRecursively(structure, invisibleRootNode, processTypeMap); + Map viewCache = new HashMap<>(); + buildStructureTreeRecursively(structure, invisibleRootNode, processTypeMap, viewCache); return invisibleRootNode; } @@ -603,18 +604,20 @@ private String buildPageRangeFromLogicalDivision(LogicalDivision structure) { * @param structure the logical division * @return the StructureTreeNode instance */ - private StructureTreeNode buildStructureTreeNode(LogicalDivision structure, Map idTypeMap) { + private StructureTreeNode buildStructureTreeNode(LogicalDivision structure, Map idTypeMap, + Map viewCache) { StructureTreeNode node; if (Objects.isNull(structure.getLink())) { - StructuralElementViewInterface divisionView = dataEditor.getRulesetManagement().getStructuralElementView( - structure.getType(), dataEditor.getAcquisitionStage(), dataEditor.getPriorityList()); + StructuralElementViewInterface divisionView = viewCache.computeIfAbsent(structure.getType(), key -> + dataEditor.getRulesetManagement().getStructuralElementView( + key, dataEditor.getAcquisitionStage(), dataEditor.getPriorityList()) + ); String label = divisionView.getLabel(); String pageRange = buildPageRangeFromLogicalDivision(structure); boolean undefined = divisionView.isUndefined() && Objects.nonNull(structure.getType()); node = new StructureTreeNode(label, pageRange, undefined, false, structure); } else { node = new StructureTreeNode(structure.getLink().getUri().toString(), null, true, true, structure); - Map viewCache = new HashMap<>(); for (Process child : dataEditor.getCurrentChildren()) { if (child.getId() == ServiceManager.getProcessService().processIdFromUri(structure.getLink().getUri())) { String type = idTypeMap.get(child.getId()); @@ -640,8 +643,8 @@ private StructureTreeNode buildStructureTreeNode(LogicalDivision structure, Map * @return a collection of views that contains all views of the full sub-tree */ private Collection buildStructureTreeRecursively(LogicalDivision structure, TreeNode result, Map processTypeMap) { - StructureTreeNode node = buildStructureTreeNode(structure, processTypeMap); + String> processTypeMap, Map viewCache) { + StructureTreeNode node = buildStructureTreeNode(structure, processTypeMap, viewCache); /* * Creating the tree node by handing over the parent node automatically * appends it to the parent as a child. That’s the logic of the JSF @@ -655,7 +658,7 @@ private Collection buildStructureTreeRecursively(LogicalDivision structure Set viewsShowingOnAChild = new HashSet<>(); if (!this.logicalStructureTreeContainsMedia()) { for (LogicalDivision child : structure.getChildren()) { - viewsShowingOnAChild.addAll(buildStructureTreeRecursively(child, parent, processTypeMap)); + viewsShowingOnAChild.addAll(buildStructureTreeRecursively(child, parent, processTypeMap, viewCache)); } } else { // iterate through children and views ordered by the ORDER attribute @@ -663,7 +666,8 @@ private Collection buildStructureTreeRecursively(LogicalDivision structure for (Pair pair : merged) { if (Objects.nonNull(pair.getRight())) { // add child and their views - viewsShowingOnAChild.addAll(buildStructureTreeRecursively(pair.getRight(), parent, processTypeMap)); + viewsShowingOnAChild.addAll(buildStructureTreeRecursively(pair.getRight(), parent, + processTypeMap, viewCache)); } else if (!viewsShowingOnAChild.contains(pair.getLeft())) { // add views of current logical division as leaf nodes DefaultTreeNode viewNode = addTreeNode(buildViewLabel(pair.getLeft()), false, false, pair.getLeft(), parent); diff --git a/Kitodo/src/test/java/org/kitodo/production/forms/dataeditor/StructurePanelTest.java b/Kitodo/src/test/java/org/kitodo/production/forms/dataeditor/StructurePanelTest.java index 52e698c3f18..76326b54068 100644 --- a/Kitodo/src/test/java/org/kitodo/production/forms/dataeditor/StructurePanelTest.java +++ b/Kitodo/src/test/java/org/kitodo/production/forms/dataeditor/StructurePanelTest.java @@ -22,6 +22,7 @@ import org.junit.jupiter.api.Test; import org.kitodo.DummyRulesetManagement; +import org.kitodo.api.dataeditor.rulesetmanagement.StructuralElementViewInterface; import org.kitodo.api.dataformat.LogicalDivision; import org.kitodo.api.dataformat.mets.LinkedMetsResource; import org.kitodo.data.database.beans.Process; @@ -51,13 +52,14 @@ public void testBuildStructureTreeRecursively() throws Exception { link.setUri(URI.create("database://?process.id=42")); structure.setLink(link); Map processTypeMap = new HashMap<>(); + Map viewCache = new HashMap<>(); processTypeMap.put(ServiceManager.getProcessService().processIdFromUri(link.getUri()), "Monograph"); TreeNode result = new DefaultTreeNode(); Method buildStructureTreeRecursively = StructurePanel.class.getDeclaredMethod("buildStructureTreeRecursively", - LogicalDivision.class, TreeNode.class, Map.class); + LogicalDivision.class, TreeNode.class, Map.class, Map.class); buildStructureTreeRecursively.setAccessible(true); - buildStructureTreeRecursively.invoke(underTest, structure, result, processTypeMap); + buildStructureTreeRecursively.invoke(underTest, structure, result, processTypeMap, viewCache); assertTrue(((StructureTreeNode) result.getChildren().get(0).getData()).isLinked()); } From 580ab161b667e05eb1f8ed30ea46d3f96177a1ee Mon Sep 17 00:00:00 2001 From: BartChris Date: Fri, 30 Aug 2024 16:57:37 +0200 Subject: [PATCH 4/4] Add missing JavaDoc --- .../kitodo/production/forms/dataeditor/StructurePanel.java | 7 +++++-- .../kitodo/production/services/data/ProcessService.java | 7 +++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/Kitodo/src/main/java/org/kitodo/production/forms/dataeditor/StructurePanel.java b/Kitodo/src/main/java/org/kitodo/production/forms/dataeditor/StructurePanel.java index 680c7084812..0c55b5d313f 100644 --- a/Kitodo/src/main/java/org/kitodo/production/forms/dataeditor/StructurePanel.java +++ b/Kitodo/src/main/java/org/kitodo/production/forms/dataeditor/StructurePanel.java @@ -601,8 +601,10 @@ private String buildPageRangeFromLogicalDivision(LogicalDivision structure) { /** * Build a StructureTreeNode for a logical division, which is then visualized in the logical structure tree. * - * @param structure the logical division - * @return the StructureTreeNode instance + * @param structure the logical division for which the tree node is being constructed + * @param idTypeMap the mapping of process id to basetype + * @param viewCache a cache for storing and retrieving already processed StructuralElementViews + * @return the constructed {@link StructureTreeNode} instance representing the given logical division */ private StructureTreeNode buildStructureTreeNode(LogicalDivision structure, Map idTypeMap, Map viewCache) { @@ -640,6 +642,7 @@ private StructureTreeNode buildStructureTreeNode(LogicalDivision structure, Map * @param structure the current logical structure * @param result the current corresponding primefaces tree node * @param processTypeMap the mapping of process id to basetype + * @param viewCache a cache for storing and retrieving already processed StructuralElementViews * @return a collection of views that contains all views of the full sub-tree */ private Collection buildStructureTreeRecursively(LogicalDivision structure, TreeNode result, Map getIdBaseTypeMap(List processIds) throws DataException { return fetchIdToBaseTypeMap(processIds); }