Skip to content

Commit

Permalink
Partial apply PR 6185 (test adjustments are missing)
Browse files Browse the repository at this point in the history
  • Loading branch information
henning-gerhardt committed Oct 2, 2024
1 parent 5925838 commit 13a4fb7
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
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;

Expand All @@ -25,6 +27,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;
Expand All @@ -36,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;
Expand Down Expand Up @@ -193,6 +199,42 @@ SearchHits getDocument(String type, QueryBuilder query, SortBuilder sort, Intege
}
}

/**
* Retrieves a map of document IDs to their corresponding base type for the given list of IDs.
*
* @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 Map<Integer, String> fetchIdToBaseTypeMap(String type, List<Integer> ids) throws CustomResponseException, DataException {
Map<Integer, String> idToBaseTypeMap = new HashMap<>();

try {
// Create a MultiGetRequest to fetch multiple documents with only baseType field
MultiGetRequest multiGetRequest = new MultiGetRequest();
for (Integer id : ids) {
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()) {
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 | NumberFormatException e) {
throw new DataException(e);
}

return idToBaseTypeMap;
}

private String performRequest(String type, HttpEntity entity, String httpMethod, String urlRequest)
throws CustomResponseException, DataException {
String output = "";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,19 @@ public Aggregations aggregateDocuments(QueryBuilder query, AggregationBuilder ag
return restClient.aggregateDocuments(this.type, query, aggregation);
}

/**
* Retrieves a mapping of document IDs to their corresponding base type for the given list of IDs.
* Delegates to the `SearchRestClient`.
*
* @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 Map<Integer, String> fetchIdToBaseTypeMap(List<Integer> ids) throws CustomResponseException, DataException {
SearchRestClient restClient = initiateRestClient();
return restClient.fetchIdToBaseTypeMap(this.type,ids);
}

/**
* Find document by id.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -517,10 +517,29 @@ private DefaultTreeNode buildStructureTree() {
DefaultTreeNode invisibleRootNode = new DefaultTreeNode();
invisibleRootNode.setExpanded(true);
addParentLinksRecursive(dataEditor.getProcess(), invisibleRootNode);
buildStructureTreeRecursively(structure, invisibleRootNode);
List<Integer> processIds = getAllLinkedProcessIds(structure);
Map<Integer, String> processTypeMap = processIds.isEmpty() ? Collections.emptyMap() : fetchProcessTypes(processIds);
Map<String, StructuralElementViewInterface> viewCache = new HashMap<>();
buildStructureTreeRecursively(structure, invisibleRootNode, processTypeMap, viewCache);
return invisibleRootNode;
}

private List<Integer> 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<Integer, String> fetchProcessTypes(List<Integer> 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.
Expand All @@ -541,33 +560,35 @@ 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) {
private StructureTreeNode buildStructureTreeNode(LogicalDivision structure, Map<Integer, String> idTypeMap,
Map<String, StructuralElementViewInterface> 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);
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);
}
}
}
Expand All @@ -579,10 +600,13 @@ 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
* @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<View> buildStructureTreeRecursively(LogicalDivision structure, TreeNode result) {
StructureTreeNode node = buildStructureTreeNode(structure);
private Collection<View> buildStructureTreeRecursively(LogicalDivision structure, TreeNode result, Map<Integer,
String> processTypeMap, Map<String, StructuralElementViewInterface> 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
Expand All @@ -596,15 +620,16 @@ private Collection<View> buildStructureTreeRecursively(LogicalDivision structure
Set<View> viewsShowingOnAChild = new HashSet<>();
if (!this.logicalStructureTreeContainsMedia()) {
for (LogicalDivision child : structure.getChildren()) {
viewsShowingOnAChild.addAll(buildStructureTreeRecursively(child, parent));
viewsShowingOnAChild.addAll(buildStructureTreeRecursively(child, parent, processTypeMap, viewCache));
}
} else {
// iterate through children and views ordered by the ORDER attribute
List<Pair<View, LogicalDivision>> merged = mergeLogicalStructureViewsAndChildren(structure);
for (Pair<View, LogicalDivision> 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, viewCache));
} else if (!viewsShowingOnAChild.contains(pair.getLeft())) {
// add views of current logical division as leaf nodes
addTreeNode(buildViewLabel(pair.getLeft()), false, false, pair.getLeft(), parent);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1715,6 +1715,17 @@ public String getBaseType(int processId) throws DataException {
return "";
}

/**
* Retrieves a mapping of process IDs to their corresponding base types.
*
* @param processIds
* 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<Integer, String> getIdBaseTypeMap(List<Integer> processIds) throws DataException {
return fetchIdToBaseTypeMap(processIds);
}

/**
* Filter for correction / solution messages.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -458,6 +459,21 @@ public S findById(Integer id, boolean related) throws DataException {
}
}

/**
* 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<Integer, String> fetchIdToBaseTypeMap(List<Integer> ids) throws DataException {
try {
return searcher.fetchIdToBaseTypeMap(ids);
} catch (CustomResponseException e) {
throw new DataException(e);
}
}

/**
* Find list of DTO objects by query.
*
Expand Down

0 comments on commit 13a4fb7

Please sign in to comment.