Skip to content

Commit c686e82

Browse files
committed
More optimizations
1 parent 09a013b commit c686e82

File tree

11 files changed

+225
-73
lines changed

11 files changed

+225
-73
lines changed

Kitodo-DataManagement/src/main/java/org/kitodo/data/database/persistence/TaskDAO.java

Lines changed: 22 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
package org.kitodo.data.database.persistence;
1313

14+
import java.util.ArrayList;
1415
import java.util.EnumMap;
1516
import java.util.HashMap;
1617
import java.util.List;
@@ -159,7 +160,7 @@ public Map<TaskStatus, Integer> countTaskStatusForProcessAndItsAncestors(Process
159160
if (Objects.isNull(process.getId())) {
160161
throw new DAOException("can not count task status for process that has id of null");
161162
}
162-
163+
163164
// initialize counts
164165
Map<TaskStatus, Integer> counts = new HashMap<>();
165166
counts.put(TaskStatus.OPEN, 0);
@@ -198,22 +199,24 @@ public Map<TaskStatus, Integer> countTaskStatusForProcessAndItsAncestors(Process
198199
}
199200
}
200201

202+
/**
203+
* Loads task status counts for the given processes including all their descendant processes.
204+
*
205+
* <p>The result maps each root process ID to a count per TaskStatus.</p>
206+
*
207+
* @param processIds the IDs of the root processes to query
208+
* @return a map of process ID to task status counts
209+
*/
201210
@SuppressWarnings("unchecked")
202-
public Map<Integer, EnumMap<TaskStatus, Integer>>
203-
loadTaskStatusCountsForProcesses(List<Integer> processIds) throws DAOException {
204-
211+
public Map<Integer, EnumMap<TaskStatus, Integer>> loadTaskStatusCountsForProcesses(
212+
List<Integer> processIds) throws DAOException {
205213
Map<Integer, EnumMap<TaskStatus, Integer>> result = new HashMap<>();
206-
207214
if (processIds == null || processIds.isEmpty()) {
208215
return result;
209216
}
210-
211-
Stopwatch stopwatch = new Stopwatch(this,
212-
"loadTaskStatusCountsForProcesses",
217+
Stopwatch stopwatch = new Stopwatch(this,"loadTaskStatusCountsForProcesses",
213218
"processIds", processIds.toString());
214-
215219
try (Session session = HibernateUtil.getSession()) {
216-
217220
NativeQuery<Object[]> query = session.createNativeQuery(
218221
"WITH RECURSIVE process_tree (root_id, id) AS ("
219222
+ " SELECT p.id, p.id FROM process p WHERE p.id IN (:ids) "
@@ -237,35 +240,28 @@ public Map<TaskStatus, Integer> countTaskStatusForProcessAndItsAncestors(Process
237240
query.addScalar("cnt", StandardBasicTypes.INTEGER);
238241

239242
List<Object[]> rows = query.list();
240-
241243
for (Object[] row : rows) {
242244
Integer rootId = (Integer) row[0];
243245
Integer statusValue = (Integer) row[1];
244246
Integer count = (Integer) row[2];
245247

246248
EnumMap<TaskStatus, Integer> map =
247-
result.computeIfAbsent(rootId, id -> {
248-
EnumMap<TaskStatus, Integer> m =
249-
new EnumMap<>(TaskStatus.class);
250-
for (TaskStatus s : TaskStatus.values()) {
251-
m.put(s, 0);
252-
}
253-
return m;
254-
});
255-
249+
result.computeIfAbsent(rootId, id -> createEmptyStatusMap());
256250
if (statusValue != null) {
257-
TaskStatus status =
258-
TaskStatus.getStatusFromValue(statusValue);
259-
map.put(status, count);
251+
map.put(TaskStatus.getStatusFromValue(statusValue), count);
260252
}
261253
}
262-
263254
return stopwatch.stop(result);
264-
265255
} catch (PersistenceException e) {
266256
throw new DAOException(e);
267257
}
268258
}
269259

270-
260+
private static EnumMap<TaskStatus, Integer> createEmptyStatusMap() {
261+
EnumMap<TaskStatus, Integer> map = new EnumMap<>(TaskStatus.class);
262+
for (TaskStatus s : TaskStatus.values()) {
263+
map.put(s, 0);
264+
}
265+
return map;
266+
}
271267
}

Kitodo/src/main/java/org/kitodo/production/forms/ProcessForm.java

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@ public class ProcessForm extends TemplateBaseForm {
105105
private final Map<Integer, Boolean> assignedProcesses = new HashMap<>();
106106
private String settingImportConfigurationResultMessage;
107107
private boolean importConfigurationsSetSuccessfully = false;
108+
private boolean initialized = false;
109+
108110

109111
@Inject
110112
private CustomListColumnInitializer initializer;
@@ -149,6 +151,10 @@ public void init() {
149151
stopwatch.stop();
150152
}
151153

154+
/**
155+
* Executes navigation logic when entering the view from the desktop.
156+
*/
157+
152158
/**
153159
* Return list of process properties configured as custom list columns in kitodo
154160
* configuration.
@@ -1058,20 +1064,6 @@ public void setFilter(String filter) {
10581064
stopwatch.stop();
10591065
}
10601066

1061-
/**
1062-
* Returns a String containing titles of all current tasks of the given process, e.g. "OPEN" tasks and tasks
1063-
* "INWORK".
1064-
*
1065-
* @param process
1066-
* process for which current task titles are returned
1067-
* @return String containing titles of current tasks of given process
1068-
*/
1069-
public String getCurrentTaskTitles(Process process) {
1070-
Stopwatch stopwatch = new Stopwatch(this.getClass(), process, "getCurrentTaskTitles");
1071-
return stopwatch.stop(ServiceManager.getProcessService().createProgressTooltip(process));
1072-
1073-
}
1074-
10751067
/**
10761068
* Get all parent processes recursively for the given process.
10771069
*

Kitodo/src/main/java/org/kitodo/production/forms/ProcessListBaseView.java

Lines changed: 103 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515

1616
import java.io.IOException;
1717
import java.net.URI;
18-
1918
import java.util.ArrayList;
2019
import java.util.EnumMap;
2120
import java.util.HashMap;
@@ -24,7 +23,6 @@
2423
import java.util.Map;
2524
import java.util.Objects;
2625

27-
2826
import org.apache.logging.log4j.LogManager;
2927
import org.apache.logging.log4j.Logger;
3028
import org.kitodo.api.dataformat.PhysicalDivision;
@@ -68,10 +66,12 @@ public class ProcessListBaseView extends BaseForm {
6866
DeleteProcessDialog deleteProcessDialog = new DeleteProcessDialog();
6967

7068
private final HashMap<Integer, Boolean> exportable = new HashMap<>();
69+
private static final String NL = "\n";
7170

7271
boolean allSelected = false;
7372
HashSet<Integer> excludedProcessIds = new HashSet<>();
7473

74+
7575
/**
7676
* Constructor.
7777
*/
@@ -173,11 +173,89 @@ private LazyProcessModel getLazyProcessModel() {
173173
return (LazyProcessModel) this.lazyBeanModel;
174174
}
175175

176+
/**
177+
* Checks whether the given process has any tasks at all.
178+
*
179+
* @param process the process to check
180+
* @return true if at least one task exists, otherwise false
181+
*/
182+
public boolean hasAnyTasks(Process process) {
183+
Map<TaskStatus, Integer> counts = getCachedTaskStatusCounts(process);
184+
return counts.values().stream().mapToInt(Integer::intValue).sum() > 0;
185+
}
186+
187+
/**
188+
* Checks whether the given process has child processes.
189+
*
190+
* @param process the process to check
191+
* @return true if the process has children, otherwise false
192+
*/
193+
public boolean hasChildren(Process process) {
194+
return getLazyProcessModel().getProcessesWithChildren().contains(process.getId());
195+
}
196+
197+
/**
198+
* Returns the titles of open and in-work tasks for the given process.
199+
*
200+
* <p>For parent processes, no task titles are returned.</p>
201+
*
202+
* @param process the process to get task titles for
203+
* @return formatted task titles or an empty string if none exist
204+
*/
205+
public String getCurrentTaskTitles(Process process) {
206+
Map<TaskStatus, List<String>> titles =
207+
getLazyProcessModel().getTaskTitleCache().get(process.getId());
208+
209+
if (hasChildren(process)) {
210+
return null;
211+
}
212+
213+
if (Objects.isNull(titles) || titles.isEmpty()) {
214+
return "";
215+
}
216+
217+
StringBuilder sb = new StringBuilder();
218+
appendTitles(sb, TaskStatus.OPEN, titles);
219+
appendTitles(sb, TaskStatus.INWORK, titles);
220+
return sb.toString();
221+
}
222+
223+
/**
224+
* Appends task titles of the given status to the provided StringBuilder.
225+
*
226+
* @param sb the StringBuilder to append to
227+
* @param status the task status to append
228+
* @param titles task titles grouped by status
229+
*/
230+
private void appendTitles(StringBuilder sb,
231+
TaskStatus status,
232+
Map<TaskStatus, List<String>> titles) {
233+
List<String> list = titles.get(status);
234+
if (Objects.isNull(list) || list.isEmpty()) {
235+
return;
236+
}
237+
if (!sb.isEmpty()) {
238+
sb.append(NL);
239+
}
240+
sb.append(Helper.getTranslation(status.getTitle())).append(":");
241+
for (String t : list) {
242+
sb.append(NL).append(" - ").append(Helper.getTranslation(t));
243+
}
244+
}
245+
246+
/**
247+
* Returns cached task status counts for the given process.
248+
*
249+
* <p>If no cached data exists, a fallback database query is executed.</p>
250+
*
251+
* @param process the process to get task status counts for
252+
* @return a map of task status to count
253+
*/
176254
public Map<TaskStatus, Integer> getCachedTaskStatusCounts(Process process) {
177255
LazyProcessModel model = getLazyProcessModel();
178256
EnumMap<TaskStatus, Integer> cached = model.getTaskStatusCounts(process);
179257

180-
if (cached != null) {
258+
if (Objects.nonNull(cached)) {
181259
return cached;
182260
}
183261
// fallback (should rarely happen)
@@ -189,27 +267,40 @@ public Map<TaskStatus, Integer> getCachedTaskStatusCounts(Process process) {
189267
}
190268
}
191269

270+
/**
271+
* Calculates the percentage of tasks with the given status.
272+
*
273+
* @param process the process to calculate progress for
274+
* @param status the task status to calculate
275+
* @return progress percentage for the given status
276+
*/
192277
public double progress(Process process, TaskStatus status) {
193278
Map<TaskStatus, Integer> counts = getCachedTaskStatusCounts(process);
194-
195279
int total = counts.values().stream().mapToInt(Integer::intValue).sum();
196-
197280
// keep legacy semantics
198281
if (total == 0) {
199282
return status == TaskStatus.LOCKED ? 100.0 : 0.0;
200283
}
201-
202284
return 100.0 * counts.getOrDefault(status, 0) / total;
203285
}
204286

287+
/**
288+
* Returns the percentage of completed tasks.
289+
*/
205290
public double progressClosed(Process process) {
206291
return progress(process, TaskStatus.DONE);
207292
}
208293

294+
/**
295+
* Returns the percentage of tasks currently in work.
296+
*/
209297
public double progressInProcessing(Process process) {
210298
return progress(process, TaskStatus.INWORK);
211299
}
212300

301+
/**
302+
* Returns the percentage of open tasks.
303+
*/
213304
public double progressOpen(Process process) {
214305
return progress(process, TaskStatus.OPEN);
215306
}
@@ -672,7 +763,12 @@ public boolean canBeExported(Process process) {
672763
Stopwatch stopwatch = new Stopwatch(this.getClass(), process, "canBeExported");
673764
try {
674765
if (!exportable.containsKey(process.getId())) {
675-
exportable.put(process.getId(), ProcessService.canBeExported(process));
766+
boolean processHasChildren = hasChildren(process);
767+
if (processHasChildren) {
768+
exportable.put(process.getId(), true);
769+
} else {
770+
exportable.put(process.getId(), ProcessService.canBeExported(process, false));
771+
}
676772
}
677773
return stopwatch.stop(exportable.get(process.getId()));
678774
} catch (DAOException e) {

Kitodo/src/main/java/org/kitodo/production/model/LazyProcessModel.java

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,20 @@
1616
import java.util.ArrayList;
1717
import java.util.EnumMap;
1818
import java.util.HashMap;
19+
import java.util.HashSet;
1920
import java.util.LinkedList;
2021
import java.util.List;
2122
import java.util.Map;
2223
import java.util.Objects;
24+
import java.util.Set;
2325

2426
import org.apache.commons.lang3.StringUtils;
2527
import org.kitodo.data.database.beans.Process;
2628
import org.kitodo.data.database.enums.TaskStatus;
2729
import org.kitodo.data.database.exceptions.DAOException;
2830
import org.kitodo.data.database.persistence.TaskDAO;
2931
import org.kitodo.exceptions.FilterException;
32+
import org.kitodo.production.services.ServiceManager;
3033
import org.kitodo.production.services.data.FilterService;
3134
import org.kitodo.production.services.data.ProcessService;
3235
import org.kitodo.utils.Stopwatch;
@@ -56,7 +59,8 @@ public class LazyProcessModel extends LazyBeanModel {
5659
private boolean showInactiveProjects = false;
5760

5861
private Map<Integer, EnumMap<TaskStatus, Integer>> taskStatusCache = new HashMap<>();
59-
62+
public Map<Integer, Map<TaskStatus, List<String>>> taskTitleCache = new HashMap<>();
63+
private Set<Integer> processesWithChildren = new HashSet<>();
6064

6165
/**
6266
* Creates a lazyBeanModel instance that allows fetching data from the data
@@ -155,8 +159,9 @@ public List<Object> load(int first, int pageSize, Map<String, SortMeta> sortBy,
155159
Process process = (Process) o;
156160
ids.add(process.getId());
157161
}
158-
taskStatusCache =
159-
new TaskDAO().loadTaskStatusCountsForProcesses(ids);
162+
taskStatusCache = new TaskDAO().loadTaskStatusCountsForProcesses(ids);
163+
taskTitleCache = ServiceManager.getTaskService().loadTaskTitlesForProcesses(ids);
164+
processesWithChildren = ServiceManager.getProcessService().findProcessIdsWithChildren(ids);
160165
logger.trace("{} entities loaded!", entities.size());
161166
return stopwatch.stop(entities);
162167
} catch (DAOException e) {
@@ -182,12 +187,16 @@ public Object getRowData() {
182187
}
183188
}
184189

185-
public Map<Integer, EnumMap<TaskStatus, Integer>> getTaskStatusCache() {
186-
return taskStatusCache;
190+
public Map<Integer, Map<TaskStatus, List<String>>> getTaskTitleCache() {
191+
return taskTitleCache;
187192
}
188193

189194
public EnumMap<TaskStatus, Integer> getTaskStatusCounts(Process process) {
190195
return taskStatusCache.get(process.getId());
191196
}
192197

198+
public Set<Integer> getProcessesWithChildren() {
199+
return processesWithChildren;
200+
}
201+
193202
}

0 commit comments

Comments
 (0)