Skip to content

Commit 6c14534

Browse files
committed
Merge pull request 'Release v25.07' (!381) from release_25.07 into master
2 parents e0188d0 + f73aac8 commit 6c14534

File tree

38 files changed

+1825
-66
lines changed

38 files changed

+1825
-66
lines changed

Jenkinsfile

Lines changed: 62 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ pipeline {
77
disableConcurrentBuilds()
88
}
99

10+
environment {
11+
GHCR_IMAGE_BASE = 'ghcr.io/intranda/goobi-workflow'
12+
DOCKERHUB_IMAGE_BASE = 'intranda/goobi-workflow'
13+
NEXUS_IMAGE_BASE = 'nexus.intranda.com:4443/goobi-workflow'
14+
}
15+
1016
stages {
1117
stage('prepare') {
1218
agent any
@@ -191,7 +197,7 @@ pipeline {
191197
git tag -a "v${projectversion}" -m "releasing v${projectversion}" && git push origin v"${projectversion}"
192198
'''
193199
script {
194-
latestTag = sh(returnStdout: true, script:'git describe --tags --abbrev=0').trim()
200+
env.latestTag = sh(returnStdout: true, script:'git describe --tags --abbrev=0').trim()
195201
}
196202
}
197203
}
@@ -209,37 +215,71 @@ pipeline {
209215
build wait: false, job: 'goobi-workflow/goobi-docker/master', parameters: [[$class: 'StringParameterValue', name: 'UPSTREAM_BRANCH', value: String.valueOf(BRANCH_NAME)]]
210216
}
211217
}
212-
stage('build and publish production image to GitHub container registry') {
218+
stage('build and publish image to Docker registries') {
213219
agent any
214220
when {
215221
anyOf {
216222
branch 'master'
217223
branch 'hotfix_release_*'
218224
branch 'develop'
219-
expression {
220-
return env.BRANCH_NAME =~ /_docker$/
221-
}
225+
expression { return env.BRANCH_NAME =~ /_docker$/ }
222226
}
223227
}
224228
steps {
225229
unstash 'target'
226-
script {
227-
docker.withRegistry('https://ghcr.io','jenkins-github-container-registry') {
228-
dockerimage_public = docker.build("intranda/goobi-workflow:${env.BUILD_ID}_${env.GIT_COMMIT}", "--build-arg build=false .")
229-
//TODO: Activate this once we want the latest build to point to the latest release
230-
//if (env.GIT_BRANCH == 'origin/master' || env.GIT_BRANCH == 'master') {
231-
// dockerimage_public.push("latest")
232-
//}
233-
if (env.GIT_BRANCH == 'origin/develop' || env.GIT_BRANCH == 'develop') {
234-
dockerimage_public.push("develop")
235-
} else if (env.GIT_BRANCH.endsWith('_docker')) {
236-
image_tag = env.GIT_BRANCH.substring(0, env.GIT_BRANCH.size()-7).replaceAll("/","_")
237-
dockerimage_public.push(image_tag)
238-
}
239-
if (latestTag != '') {
240-
dockerimage_public.push(latestTag)
241-
}
242-
}
230+
withCredentials([
231+
usernamePassword(
232+
credentialsId: 'jenkins-github-container-registry',
233+
usernameVariable: 'GHCR_USER',
234+
passwordVariable: 'GHCR_PASS'
235+
),
236+
usernamePassword(
237+
credentialsId: '0b13af35-a2fb-41f7-8ec7-01eaddcbe99d',
238+
usernameVariable: 'DOCKERHUB_USER',
239+
passwordVariable: 'DOCKERHUB_PASS'
240+
),
241+
usernamePassword(
242+
credentialsId: 'jenkins-docker',
243+
usernameVariable: 'NEXUS_USER',
244+
passwordVariable: 'NEXUS_PASS'
245+
)
246+
]) {
247+
sh '''
248+
# Login to registries
249+
echo "$GHCR_PASS" | docker login ghcr.io -u "$GHCR_USER" --password-stdin
250+
echo "$DOCKERHUB_PASS" | docker login docker.io -u "$DOCKERHUB_USER" --password-stdin
251+
echo "$NEXUS_PASS" | docker login nexus.intranda.com:4443 -u "$NEXUS_USER" --password-stdin
252+
253+
# Setup QEMU and Buildx
254+
docker buildx create --name multiarch-builder --use || docker buildx use multiarch-builder
255+
docker buildx inspect --bootstrap
256+
257+
# Tag logic
258+
TAGS=""
259+
echo "latestTag: $latestTag"
260+
if [ ! -z "$latestTag" ]; then
261+
TAGS="$TAGS -t $GHCR_IMAGE_BASE:$latestTag -t $DOCKERHUB_IMAGE_BASE:$latestTag -t $NEXUS_IMAGE_BASE:$latestTag"
262+
fi
263+
if [ "$GIT_BRANCH" = "origin/master" ] || [ "$GIT_BRANCH" = "master" ]; then
264+
TAGS="$TAGS -t $GHCR_IMAGE_BASE:latest -t $DOCKERHUB_IMAGE_BASE:latest -t $NEXUS_IMAGE_BASE:latest"
265+
elif [ "$GIT_BRANCH" = "origin/develop" ] || [ "$GIT_BRANCH" = "develop" ]; then
266+
TAGS="$TAGS -t $GHCR_IMAGE_BASE:develop -t $DOCKERHUB_IMAGE_BASE:develop -t $NEXUS_IMAGE_BASE:develop"
267+
elif echo "$GIT_BRANCH" | grep -q "_docker$"; then
268+
TAG_SUFFIX=$(echo "$GIT_BRANCH" | sed 's/_docker$//' | sed 's|/|_|g')
269+
TAGS="$TAGS -t $GHCR_IMAGE_BASE:$TAG_SUFFIX -t $DOCKERHUB_IMAGE_BASE:$TAG_SUFFIX -t $NEXUS_IMAGE_BASE:$TAG_SUFFIX"
270+
fi
271+
272+
if [ -z "$TAGS" ]; then
273+
echo "No matching tag, skipping build."
274+
exit 0
275+
fi
276+
277+
# Build and push to all registries
278+
docker buildx build --build-arg build=false \
279+
--platform linux/amd64,linux/arm64/v8,linux/ppc64le,linux/riscv64,linux/s390x \
280+
$TAGS \
281+
--push .
282+
'''
243283
}
244284
}
245285
}

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<parent>
55
<groupId>io.goobi.workflow</groupId>
66
<artifactId>workflow-base</artifactId>
7-
<version>25.06</version>
7+
<version>25.07</version>
88
<relativePath/>
99
</parent>
1010
<artifactId>workflow-core</artifactId>

src/main/java/de/sub/goobi/persistence/managers/ProcessManager.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ public static List runSQL(String sql) {
268268
try {
269269
return ProcessMysqlHelper.runSQL(sql);
270270
} catch (SQLException e) {
271-
log.error(e);
271+
log.error("Error executing SQL query: {}", e.getMessage(), e);
272272
}
273273
return new ArrayList();
274274
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package org.goobi.managedbeans;
2+
3+
import jakarta.annotation.PostConstruct;
4+
import jakarta.inject.Named;
5+
import lombok.Data;
6+
import lombok.EqualsAndHashCode;
7+
import lombok.extern.log4j.Log4j2;
8+
import org.apache.deltaspike.core.api.scope.WindowScoped;
9+
import org.goobi.production.enums.PluginType;
10+
import org.goobi.production.plugin.PluginLoader;
11+
import org.goobi.production.plugin.interfaces.IThemePlugin;
12+
13+
import java.io.Serializable;
14+
import java.util.List;
15+
16+
@Named("ThemeBean")
17+
@WindowScoped
18+
@Data
19+
@EqualsAndHashCode(callSuper = false)
20+
@Log4j2
21+
public class ThemeBean implements Serializable {
22+
private List<IThemePlugin> themePlugins;
23+
24+
@PostConstruct
25+
public void initialize() {
26+
themePlugins = PluginLoader.getPluginList(PluginType.Theme).stream()
27+
.filter(IThemePlugin.class::isInstance)
28+
.map(p -> (IThemePlugin) p)
29+
.toList();
30+
// themePlugins.forEach(p -> {
31+
// try {
32+
// p.initialize();
33+
// } catch (Exception e) {
34+
// Helper.setFehlerMeldung("An exception occurred during plugin initialization: " + p.getTitle());
35+
// log.error("An exception occurred during plugin initialization: {}", p.getTitle(), e);
36+
// }
37+
// });
38+
}
39+
}

src/main/java/org/goobi/production/enums/PluginType.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ public enum PluginType {
4444
Administration(11, "administration", IAdministrationPlugin.class),
4545
Workflow(13, "workflow", IWorkflowPlugin.class),
4646
MetadataEditor(14, "metadata", IMetadataEditorExtension.class),
47-
Generic(15, "generic", IGenericPlugin.class);
47+
Generic(15, "generic", IGenericPlugin.class),
48+
Theme(16, "theme", IThemePlugin.class);
4849

4950
@Getter
5051
private int id;

src/main/java/org/goobi/production/flow/helper/SearchColumn.java

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,11 @@ public class SearchColumn implements Serializable {
2424

2525
private static final long serialVersionUID = -3474943392910282588L;
2626

27-
private static final String TABLE_PROJECTS = "projekte.";
28-
private static final String TABLE_PROCESSES = "prozesse.";
29-
private static final String TABLE_PROCESS_PROPERTIES = "prozesseeigenschaften.";
30-
private static final String TABLE_METADATA = "metadata.";
31-
private static final String TABLE_LOG = "log.";
27+
public static final String TABLE_PROJECTS = "projekte.";
28+
public static final String TABLE_PROCESSES = "prozesse.";
29+
public static final String TABLE_PROCESS_PROPERTIES = "property.";
30+
public static final String TABLE_METADATA = "metadata.";
31+
public static final String TABLE_LOG = "log.";
3232

3333
@Getter
3434
@Setter
@@ -82,6 +82,8 @@ public String getColumnName() {
8282
return "print";
8383
} else if (value.startsWith(TABLE_LOG)) {
8484
return "content";
85+
} else if (value.startsWith(TABLE_PROCESS_PROPERTIES)) {
86+
return "property_value";
8587
} else {
8688
return "Wert";
8789
}
@@ -93,8 +95,8 @@ public String getJoinClause() {
9395
return "";
9496
}
9597
if (value.startsWith(TABLE_PROCESS_PROPERTIES)) {
96-
return " prozesseeigenschaften " + getTableName() + " ON prozesse.ProzesseID = " + getTableName() + ".object_id AND "
97-
+ getTableName() + "object_type = 'process' AND " + getTableName() + ".Titel = \"" + value.substring(value.indexOf(".") + 1)
98+
return " properties " + getTableName() + " ON prozesse.ProzesseID = " + getTableName() + ".object_id AND "
99+
+ getTableName() + ".object_type = 'process' AND " + getTableName() + ".property_name = \"" + value.substring(value.indexOf(".") + 1)
98100
+ "\"";
99101

100102
} else if (value.startsWith(TABLE_METADATA)) {

src/main/java/org/goobi/production/flow/helper/SearchResultHelper.java

Lines changed: 45 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
package org.goobi.production.flow.helper;
22

3+
import static org.goobi.production.flow.helper.SearchColumn.TABLE_LOG;
4+
import static org.goobi.production.flow.helper.SearchColumn.TABLE_METADATA;
5+
import static org.goobi.production.flow.helper.SearchColumn.TABLE_PROCESSES;
6+
import static org.goobi.production.flow.helper.SearchColumn.TABLE_PROCESS_PROPERTIES;
7+
import static org.goobi.production.flow.helper.SearchColumn.TABLE_PROJECTS;
8+
39
/**
410
* This file is part of the Goobi Application - a Workflow tool for the support of mass digitization.
511
*
@@ -24,6 +30,9 @@
2430
import java.util.ArrayList;
2531
import java.util.Arrays;
2632
import java.util.List;
33+
import java.util.Optional;
34+
import java.util.regex.Matcher;
35+
import java.util.regex.Pattern;
2736

2837
import org.apache.commons.lang3.StringUtils;
2938
import org.apache.poi.xssf.usermodel.XSSFCell;
@@ -64,35 +73,40 @@ public class SearchResultHelper {
6473
@Getter
6574
private List<SelectItem> possibleColumns = new ArrayList<>();
6675

76+
// new constructor for junit tests
77+
SearchResultHelper(List<SelectItem> possibleColumns) {
78+
this.possibleColumns = possibleColumns;
79+
}
80+
6781
public SearchResultHelper() {
6882

6983
possibleColumns.add(new SelectItem("all", Helper.getTranslation("selectAllFields")));
7084

7185
String processData = "processData";
7286
possibleColumns.add(new SelectItem(processData, Helper.getTranslation(processData), Helper.getTranslation(processData), true));
7387

74-
String processTitle = "prozesse.Titel";
88+
String processTitle = TABLE_PROCESSES + "Titel";
7589
possibleColumns.add(new SelectItem(processTitle, Helper.getTranslation(processTitle)));
7690

77-
String processId = "prozesse.ProzesseID";
91+
String processId = TABLE_PROCESSES + "ProzesseID";
7892
possibleColumns.add(new SelectItem(processId, Helper.getTranslation(processId)));
7993

80-
String processCreationDate = "prozesse.erstellungsdatum";
94+
String processCreationDate = TABLE_PROCESSES + "erstellungsdatum";
8195
possibleColumns.add(new SelectItem(processCreationDate, Helper.getTranslation(processCreationDate)));
8296

83-
String processSortHelperImages = "prozesse.sortHelperImages";
97+
String processSortHelperImages = TABLE_PROCESSES + "sortHelperImages";
8498
possibleColumns.add(new SelectItem(processSortHelperImages, Helper.getTranslation(processSortHelperImages)));
8599

86-
String processSortHelperMetadata = "prozesse.sortHelperMetadata";
100+
String processSortHelperMetadata = TABLE_PROCESSES + "sortHelperMetadata";
87101
possibleColumns.add(new SelectItem(processSortHelperMetadata, Helper.getTranslation(processSortHelperMetadata)));
88102

89-
String processSortHelperDocstructs = "prozesse.sortHelperDocstructs";
103+
String processSortHelperDocstructs = TABLE_PROCESSES + "sortHelperDocstructs";
90104
possibleColumns.add(new SelectItem(processSortHelperDocstructs, Helper.getTranslation(processSortHelperDocstructs)));
91105

92-
String projectTitle = "projekte.Titel";
106+
String projectTitle = TABLE_PROJECTS + "Titel";
93107
possibleColumns.add(new SelectItem(projectTitle, Helper.getTranslation(projectTitle)));
94108

95-
possibleColumns.add(new SelectItem("log.lastError", Helper.getTranslation("SearchResultField_lastError")));
109+
possibleColumns.add(new SelectItem(TABLE_LOG + "lastError", Helper.getTranslation("SearchResultField_lastError")));
96110

97111
List<String> columnWhiteList = ConfigurationHelper.getInstance().getDownloadColumnWhitelist();
98112
if (columnWhiteList == null || columnWhiteList.isEmpty()) {
@@ -105,7 +119,7 @@ public SearchResultHelper() {
105119
if (!processTitles.isEmpty()) {
106120

107121
for (String title : processTitles) {
108-
String key = "prozesseeigenschaften." + title;
122+
String key = TABLE_PROCESS_PROPERTIES + title;
109123
if (columnWhiteList.contains(title)) {
110124
possibleColumns.add(new SelectItem(key, Helper.getTranslation(key)));
111125
}
@@ -118,7 +132,7 @@ public SearchResultHelper() {
118132

119133
for (String title : metadataTitles) {
120134
if (columnWhiteList.contains(title)) {
121-
String key = "metadata." + title;
135+
String key = TABLE_METADATA + title;
122136
subList.add(new SelectItem(key, Helper.getTranslation(key)));
123137
}
124138
}
@@ -274,13 +288,23 @@ public XSSFWorkbook getResult(List<SearchColumn> columnList, String filter, Stri
274288
return wb;
275289
}
276290

291+
private static final Pattern PROPERTY_ORDER_PATTERN = Pattern.compile("\\{process\\.(.*)\\}.*");
292+
277293
@SuppressWarnings({ "rawtypes", "unchecked" })
278294
private List search(List<SearchColumn> columnList, String filter, String order, boolean showClosedProcesses, boolean showArchivedProjects) {
279295
StringBuilder sb = new StringBuilder();
280296
sb.append("SELECT distinct prozesse.ProzesseID, ");
281297

298+
Optional<String> propertyOrder = Optional.empty();
299+
282300
if (StringUtils.isNotBlank(order)) {
283-
sb.append(order.replace(" desc", "").replace(" asc", "") + ", ");
301+
Matcher m = PROPERTY_ORDER_PATTERN.matcher(order);
302+
if (m.find()) {
303+
propertyOrder = Optional.of(m.group(1));
304+
sb.append("property.property_value as `" + propertyOrder.get() + "`, ");
305+
} else {
306+
sb.append(order.replace(" desc", "").replace(" asc", "") + ", ");
307+
}
284308
}
285309

286310
boolean includeLog = false;
@@ -308,6 +332,11 @@ else if (!sc.getTableName().startsWith(METADATA)) {
308332
sb.append("(select max(id) from journal where objectID = prozesse.ProzesseID and log.entrytype = 'process' and type = 'error') ");
309333
}
310334

335+
if (propertyOrder.isPresent()) {
336+
sb.append(" left join properties property on property.property_name = '" + propertyOrder.get()
337+
+ "' and property.object_id = prozesse.ProzesseID");
338+
}
339+
311340
boolean leftJoin = false;
312341

313342
for (SearchColumn sc : columnList) {
@@ -348,7 +377,11 @@ else if (!sc.getTableName().startsWith(METADATA)) {
348377
sb.append(sql);
349378

350379
if (order != null && !order.isEmpty()) {
351-
sb.append(" ORDER BY " + order);
380+
if (propertyOrder.isPresent()) {
381+
sb.append(" ORDER BY `" + propertyOrder.get() + "` " + (order.endsWith("asc") ? "asc" : "desc"));
382+
} else {
383+
sb.append(" ORDER BY " + order);
384+
}
352385
}
353386
List list = ProcessManager.runSQL(sb.toString());
354387

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package org.goobi.production.plugin.interfaces;
2+
3+
import org.goobi.production.enums.PluginType;
4+
import org.goobi.production.plugin.DockAnchor;
5+
6+
public interface IThemePlugin extends IPlugin {
7+
default String getId() {
8+
return getTitle().replaceAll("\\s+", "");
9+
}
10+
11+
@Override
12+
default PluginType getType() {
13+
return PluginType.Theme;
14+
}
15+
16+
default void initialize() throws Exception {
17+
// Nothing to do per default
18+
}
19+
20+
default void execute() throws Exception {
21+
// Nothing to do per default
22+
}
23+
24+
public default String[] getJsPaths() {
25+
return new String[0];
26+
}
27+
28+
public default String[] getCssPaths() {
29+
return new String[0];
30+
}
31+
}

0 commit comments

Comments
 (0)