diff --git a/CHANGELOG.md b/CHANGELOG.md
index a582f53bf..9b19d9888 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
## Unreleased
+### Added
+
+- New endpoint `/v6/digipress` for faster retrieval of the newspaper list (manifestations):
+ supports both filtering and sorting
+
## [9.2.1](https://github.com/dbmdz/metadata-service/releases/tag/9.2.1) - 2024-06-11
### Fixed
diff --git a/metasvc-client/pom.xml b/metasvc-client/pom.xml
index 42dd26b1d..c1d7c63f2 100644
--- a/metasvc-client/pom.xml
+++ b/metasvc-client/pom.xml
@@ -6,7 +6,7 @@
io.github.dbmdz.metadata
metasvc
- 9.2.2-SNAPSHOT
+ 9.3.0-SNAPSHOT
Metadata-Service: Repository Client
diff --git a/metasvc-client/src/main/java/de/digitalcollections/client/BaseRestClient.java b/metasvc-client/src/main/java/de/digitalcollections/client/BaseRestClient.java
index 07afc55b8..5bd63e4e6 100644
--- a/metasvc-client/src/main/java/de/digitalcollections/client/BaseRestClient.java
+++ b/metasvc-client/src/main/java/de/digitalcollections/client/BaseRestClient.java
@@ -1,11 +1,13 @@
package de.digitalcollections.client;
import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectReader;
import de.digitalcollections.model.exception.TechnicalException;
import de.digitalcollections.model.exception.http.HttpErrorDecoder;
import de.digitalcollections.model.list.ListRequest;
+import de.digitalcollections.model.list.ListResponse;
import de.digitalcollections.model.list.filtering.FilterCriteria;
import de.digitalcollections.model.list.filtering.FilterCriterion;
import de.digitalcollections.model.list.filtering.FilterLogicalOperator;
@@ -202,11 +204,41 @@ protected String doDeleteRequestForString(String requestUrl) throws TechnicalExc
}
}
+ protected ListResponse doGetRequestForObjectListResponse(
+ String requestUrl, Class targetType, ListRequest listRequest) throws TechnicalException {
+ if (listRequest != null) {
+ if (listRequest.hasFiltering())
+ requestUrl +=
+ (requestUrl.contains("?") ? "&" : "?")
+ + getFilterParamsAsString(listRequest.getFiltering());
+ if (listRequest.hasSorting())
+ requestUrl += (requestUrl.contains("?") ? "&" : "?") + getSortParams(listRequest);
+ }
+ HttpRequest req = createGetRequest(requestUrl);
+ try {
+ HttpResponse response = http.send(req, HttpResponse.BodyHandlers.ofByteArray());
+ Integer statusCode = response.statusCode();
+ if (statusCode >= 400) {
+ throw HttpErrorDecoder.decode("GET " + requestUrl, statusCode, response);
+ }
+ // This is the most performant approach for Jackson
+ final byte[] body = response.body();
+ if (body == null || body.length == 0) {
+ return null;
+ }
+ ListResponse result =
+ mapper.readerFor(new TypeReference>() {}).readValue(body);
+ return result;
+ } catch (IOException | InterruptedException e) {
+ throw new TechnicalException("Failed to retrieve response due to connection error", e);
+ }
+ }
+
protected T doGetRequestForObject(String requestUrl) throws TechnicalException {
- return (T) doGetRequestForObject(requestUrl, targetType);
+ return doGetRequestForObject(requestUrl, targetType);
}
- protected Object doGetRequestForObject(String requestUrl, Class> targetType)
+ protected U doGetRequestForObject(String requestUrl, Class targetType)
throws TechnicalException {
HttpRequest req = createGetRequest(requestUrl);
try {
@@ -220,7 +252,7 @@ protected Object doGetRequestForObject(String requestUrl, Class> targetType)
if (body == null || body.length == 0) {
return null;
}
- T result = mapper.readerFor(targetType).readValue(body);
+ U result = mapper.readerFor(targetType).readValue(body);
return result;
} catch (IOException | InterruptedException e) {
throw new TechnicalException("Failed to retrieve response due to connection error", e);
@@ -228,18 +260,28 @@ protected Object doGetRequestForObject(String requestUrl, Class> targetType)
}
protected List doGetRequestForObjectList(String requestUrl) throws TechnicalException {
- return doGetRequestForObjectList(requestUrl, targetType, null);
+ return doGetRequestForObjectList(requestUrl, targetType, (ListRequest) null);
}
- protected List doGetRequestForObjectList(String requestUrl, Class> targetType)
+ protected List doGetRequestForObjectList(String requestUrl, Class targetType)
throws TechnicalException {
- return doGetRequestForObjectList(requestUrl, targetType, null);
+ return doGetRequestForObjectList(requestUrl, targetType, (ListRequest) null);
}
- protected List doGetRequestForObjectList(
- String requestUrl, Class> targetType, Filtering filtering) throws TechnicalException {
- if (filtering != null) {
- requestUrl += (requestUrl.contains("?") ? "&" : "?") + getFilterParamsAsString(filtering);
+ protected List doGetRequestForObjectList(
+ String requestUrl, Class targetType, Filtering filtering) throws TechnicalException {
+ return doGetRequestForObjectList(requestUrl, targetType, new ListRequest(filtering));
+ }
+
+ protected List doGetRequestForObjectList(
+ String requestUrl, Class targetType, ListRequest listRequest) throws TechnicalException {
+ if (listRequest != null) {
+ if (listRequest.hasFiltering())
+ requestUrl +=
+ (requestUrl.contains("?") ? "&" : "?")
+ + getFilterParamsAsString(listRequest.getFiltering());
+ if (listRequest.hasSorting())
+ requestUrl += (requestUrl.contains("?") ? "&" : "?") + getSortParams(listRequest);
}
HttpRequest req = createGetRequest(requestUrl);
// TODO add creation of a request id if needed
@@ -255,7 +297,7 @@ protected List doGetRequestForObjectList(
if (body == null || body.length == 0) {
return null;
}
- List result = mapper.readerForListOf(targetType).readValue(body);
+ List result = mapper.readerForListOf(targetType).readValue(body);
return result;
} catch (IOException | InterruptedException e) {
throw new TechnicalException("Failed to retrieve response due to connection error", e);
@@ -295,6 +337,7 @@ protected PageResponse doGetRequestForPagedObjectList(
}
}
+ // FIXME: targetType is ignored.
protected PageResponse doGetRequestForPagedObjectList(
String requestUrl, PageRequest pageRequest, Class> targetType) throws TechnicalException {
return doGetRequestForPagedObjectList(requestUrl, pageRequest);
@@ -524,7 +567,7 @@ protected T doPutRequestForObject(String requestUrl, T object) throws TechnicalE
}
}
- protected Object doPutRequestForObject(String requestUrl, Object bodyObject, Class> targetType)
+ protected U doPutRequestForObject(String requestUrl, Object bodyObject, Class targetType)
throws TechnicalException {
try {
HttpRequest req = createPutRequest(requestUrl, bodyObject);
@@ -538,15 +581,15 @@ protected Object doPutRequestForObject(String requestUrl, Object bodyObject, Cla
if (body == null) {
return null;
}
- Object result = mapper.readerFor(targetType).readValue(body);
+ U result = mapper.readerFor(targetType).readValue(body);
return result;
} catch (IOException | InterruptedException e) {
throw new TechnicalException("Failed to retrieve response due to error", e);
}
}
- protected List> doPutRequestForObjectList(
- String requestUrl, List> list, Class> targetType) throws TechnicalException {
+ protected List doPutRequestForObjectList(
+ String requestUrl, List> list, Class targetType) throws TechnicalException {
try {
HttpRequest req = createPutRequest(requestUrl, list);
HttpResponse response = http.send(req, HttpResponse.BodyHandlers.ofByteArray());
@@ -559,7 +602,7 @@ protected List> doPutRequestForObjectList(
if (body == null || body.length == 0) {
return null;
}
- List> result = mapper.readerForListOf(targetType).readValue(body);
+ List result = mapper.readerForListOf(targetType).readValue(body);
return result;
} catch (IOException | InterruptedException e) {
throw new TechnicalException("Failed to retrieve response due to error", e);
diff --git a/metasvc-client/src/main/java/de/digitalcollections/cudami/client/identifiable/entity/work/CudamiManifestationsClient.java b/metasvc-client/src/main/java/de/digitalcollections/cudami/client/identifiable/entity/work/CudamiManifestationsClient.java
index 97a985837..712d18433 100644
--- a/metasvc-client/src/main/java/de/digitalcollections/cudami/client/identifiable/entity/work/CudamiManifestationsClient.java
+++ b/metasvc-client/src/main/java/de/digitalcollections/cudami/client/identifiable/entity/work/CudamiManifestationsClient.java
@@ -5,8 +5,11 @@
import de.digitalcollections.model.exception.TechnicalException;
import de.digitalcollections.model.identifiable.entity.item.Item;
import de.digitalcollections.model.identifiable.entity.manifestation.Manifestation;
+import de.digitalcollections.model.list.ListRequest;
+import de.digitalcollections.model.list.ListResponse;
import de.digitalcollections.model.list.paging.PageRequest;
import de.digitalcollections.model.list.paging.PageResponse;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.net.http.HttpClient;
import java.util.List;
import java.util.Locale;
@@ -14,6 +17,9 @@
public class CudamiManifestationsClient extends CudamiEntitiesClient {
+ @SuppressFBWarnings(value = "SS_SHOULD_BE_STATIC", justification = "non-static is fine, though")
+ private final String digiPressBaseEndpoint = API_VERSION_PREFIX + "/digipress";
+
public CudamiManifestationsClient(HttpClient http, String serverUrl, ObjectMapper mapper) {
super(http, serverUrl, Manifestation.class, mapper, API_VERSION_PREFIX + "/manifestations");
}
@@ -34,4 +40,13 @@ public List getLanguagesOfItems(UUID uuid) throws TechnicalException {
return doGetRequestForObjectList(
String.format("%s/%s/items/languages", baseEndpoint, uuid), Locale.class);
}
+
+ public ListResponse findNewspapers(ListRequest listRequest)
+ throws TechnicalException {
+ return doGetRequestForObjectListResponse(digiPressBaseEndpoint, targetType, listRequest);
+ }
+
+ public void refreshNewspapers() throws TechnicalException {
+ doPutRequestForObject(digiPressBaseEndpoint + "/refresh", null);
+ }
}
diff --git a/metasvc-client/src/main/java/de/digitalcollections/cudami/client/identifiable/entity/work/CudamiWorksClient.java b/metasvc-client/src/main/java/de/digitalcollections/cudami/client/identifiable/entity/work/CudamiWorksClient.java
index 0d4f6a52f..0b4c634f3 100644
--- a/metasvc-client/src/main/java/de/digitalcollections/cudami/client/identifiable/entity/work/CudamiWorksClient.java
+++ b/metasvc-client/src/main/java/de/digitalcollections/cudami/client/identifiable/entity/work/CudamiWorksClient.java
@@ -4,7 +4,6 @@
import de.digitalcollections.cudami.client.identifiable.entity.CudamiEntitiesClient;
import de.digitalcollections.model.exception.TechnicalException;
import de.digitalcollections.model.identifiable.entity.agent.Agent;
-import de.digitalcollections.model.identifiable.entity.digitalobject.DigitalObject;
import de.digitalcollections.model.identifiable.entity.manifestation.Manifestation;
import de.digitalcollections.model.identifiable.entity.work.Work;
import de.digitalcollections.model.list.paging.PageRequest;
@@ -23,8 +22,7 @@ public CudamiWorksClient(HttpClient http, String serverUrl, ObjectMapper mapper)
public Set getCreators(UUID uuid) throws TechnicalException {
return (Set)
- doGetRequestForObjectList(
- String.format("%s/%s/creators", baseEndpoint, uuid), DigitalObject.class);
+ doGetRequestForObjectList(String.format("%s/%s/creators", baseEndpoint, uuid), Agent.class);
}
public PageResponse findChildren(UUID uuid, PageRequest pageRequest)
diff --git a/metasvc-lobid-client/pom.xml b/metasvc-lobid-client/pom.xml
index 26e1b92dc..ffde81c0c 100644
--- a/metasvc-lobid-client/pom.xml
+++ b/metasvc-lobid-client/pom.xml
@@ -7,7 +7,7 @@
io.github.dbmdz.metadata
metasvc
- 9.2.2-SNAPSHOT
+ 9.3.0-SNAPSHOT
Metadata-Service: lobid.org Client
diff --git a/metasvc-model/pom.xml b/metasvc-model/pom.xml
index 85d3d598a..2d5207889 100644
--- a/metasvc-model/pom.xml
+++ b/metasvc-model/pom.xml
@@ -6,7 +6,7 @@
io.github.dbmdz.metadata
metasvc
- 9.2.2-SNAPSHOT
+ 9.3.0-SNAPSHOT
Metadata-Service: Model
diff --git a/metasvc-model/src/main/java/de/digitalcollections/model/list/ListRequest.java b/metasvc-model/src/main/java/de/digitalcollections/model/list/ListRequest.java
index 3d3ed157d..31a590c85 100644
--- a/metasvc-model/src/main/java/de/digitalcollections/model/list/ListRequest.java
+++ b/metasvc-model/src/main/java/de/digitalcollections/model/list/ListRequest.java
@@ -40,6 +40,10 @@ public ListRequest(Sorting sorting) {
this(sorting, null, null);
}
+ public ListRequest(Filtering filtering) {
+ this(null, filtering, null);
+ }
+
/**
* Creates a new {@link ListRequest} with sorting parameters applied.
*
diff --git a/metasvc-server/backend-api/pom.xml b/metasvc-server/backend-api/pom.xml
index f147867c5..5711c9cd4 100644
--- a/metasvc-server/backend-api/pom.xml
+++ b/metasvc-server/backend-api/pom.xml
@@ -6,7 +6,7 @@
io.github.dbmdz.metadata
metasvc-server
- 9.2.2-SNAPSHOT
+ 9.3.0-SNAPSHOT
Metadata-Service: Repository Server (Backend API)
diff --git a/metasvc-server/backend-api/src/main/java/io/github/dbmdz/metadata/server/backend/api/repository/identifiable/entity/work/DigipressManifestationRepository.java b/metasvc-server/backend-api/src/main/java/io/github/dbmdz/metadata/server/backend/api/repository/identifiable/entity/work/DigipressManifestationRepository.java
new file mode 100644
index 000000000..dce21e89d
--- /dev/null
+++ b/metasvc-server/backend-api/src/main/java/io/github/dbmdz/metadata/server/backend/api/repository/identifiable/entity/work/DigipressManifestationRepository.java
@@ -0,0 +1,14 @@
+package io.github.dbmdz.metadata.server.backend.api.repository.identifiable.entity.work;
+
+import de.digitalcollections.model.identifiable.entity.manifestation.Manifestation;
+import de.digitalcollections.model.list.ListRequest;
+import de.digitalcollections.model.list.ListResponse;
+import io.github.dbmdz.metadata.server.backend.api.repository.exceptions.RepositoryException;
+
+public interface DigipressManifestationRepository {
+
+ void refreshTable();
+
+ ListResponse getNewspapers(ListRequest listRequest)
+ throws RepositoryException;
+}
diff --git a/metasvc-server/backend-file/pom.xml b/metasvc-server/backend-file/pom.xml
index 5d866c378..7d4a42bd4 100644
--- a/metasvc-server/backend-file/pom.xml
+++ b/metasvc-server/backend-file/pom.xml
@@ -5,7 +5,7 @@
io.github.dbmdz.metadata
metasvc-server
- 9.2.2-SNAPSHOT
+ 9.3.0-SNAPSHOT
Metadata-Service: Repository Server (Backend IMPL File)
diff --git a/metasvc-server/backend-inmemory/pom.xml b/metasvc-server/backend-inmemory/pom.xml
index 043ee1ca5..7e9ad2bfd 100644
--- a/metasvc-server/backend-inmemory/pom.xml
+++ b/metasvc-server/backend-inmemory/pom.xml
@@ -6,7 +6,7 @@
io.github.dbmdz.metadata
metasvc-server
- 9.2.2-SNAPSHOT
+ 9.3.0-SNAPSHOT
Metadata-Service: Repository Server (Backend IMPL InMemory)
diff --git a/metasvc-server/backend-jdbi/pom.xml b/metasvc-server/backend-jdbi/pom.xml
index a4e325c5b..842b7dd59 100644
--- a/metasvc-server/backend-jdbi/pom.xml
+++ b/metasvc-server/backend-jdbi/pom.xml
@@ -8,7 +8,7 @@
io.github.dbmdz.metadata
metasvc-server
- 9.2.2-SNAPSHOT
+ 9.3.0-SNAPSHOT
Metadata-Service: Repository Server (Backend IMPL JDBI PostgreSql)
diff --git a/metasvc-server/backend-jdbi/src/main/java/io/github/dbmdz/metadata/server/backend/impl/database/AbstractPagingSortingFilteringRepositoryImpl.java b/metasvc-server/backend-jdbi/src/main/java/io/github/dbmdz/metadata/server/backend/impl/database/AbstractPagingSortingFilteringRepositoryImpl.java
index 5a958f141..7d7b9c535 100644
--- a/metasvc-server/backend-jdbi/src/main/java/io/github/dbmdz/metadata/server/backend/impl/database/AbstractPagingSortingFilteringRepositoryImpl.java
+++ b/metasvc-server/backend-jdbi/src/main/java/io/github/dbmdz/metadata/server/backend/impl/database/AbstractPagingSortingFilteringRepositoryImpl.java
@@ -46,20 +46,20 @@ private void addOffset(PageRequest pageRequest, StringBuilder sqlQuery) {
}
}
- protected void addOrderBy(PageRequest pageRequest, StringBuilder sqlQuery) {
- if (pageRequest != null) {
- // Sorting
- Sorting sorting = pageRequest.getSorting();
- String orderBy = getOrderBy(sorting);
- if (StringUtils.hasText(orderBy)) {
- if (!sqlQuery.toString().matches("(?i).* order by .*")) {
- sqlQuery.append(" ORDER BY ");
- } else {
- sqlQuery.append(", ");
- }
- sqlQuery.append(orderBy);
- }
+ protected void addOrderBy(Sorting sorting, StringBuilder sqlQuery) {
+ Optional orderBy =
+ Optional.ofNullable(sorting).map(this::getOrderBy).filter(StringUtils::hasText);
+ if (orderBy.isEmpty()) return;
+ if (!sqlQuery.toString().matches("(?i).* order by .*")) {
+ sqlQuery.append(" ORDER BY ");
+ } else {
+ sqlQuery.append(", ");
}
+ sqlQuery.append(orderBy.get());
+ }
+
+ protected void addOrderBy(PageRequest pageRequest, StringBuilder sqlQuery) {
+ if (pageRequest != null) addOrderBy(pageRequest.getSorting(), sqlQuery);
}
/*
diff --git a/metasvc-server/backend-jdbi/src/main/java/io/github/dbmdz/metadata/server/backend/impl/jdbi/identifiable/entity/work/DigipressManifestationRepositoryImpl.java b/metasvc-server/backend-jdbi/src/main/java/io/github/dbmdz/metadata/server/backend/impl/jdbi/identifiable/entity/work/DigipressManifestationRepositoryImpl.java
new file mode 100644
index 000000000..ac41960f6
--- /dev/null
+++ b/metasvc-server/backend-jdbi/src/main/java/io/github/dbmdz/metadata/server/backend/impl/jdbi/identifiable/entity/work/DigipressManifestationRepositoryImpl.java
@@ -0,0 +1,104 @@
+package io.github.dbmdz.metadata.server.backend.impl.jdbi.identifiable.entity.work;
+
+import de.digitalcollections.cudami.model.config.CudamiConfig;
+import de.digitalcollections.model.identifiable.entity.Entity;
+import de.digitalcollections.model.identifiable.entity.agent.Agent;
+import de.digitalcollections.model.identifiable.entity.manifestation.Manifestation;
+import de.digitalcollections.model.list.ListRequest;
+import de.digitalcollections.model.list.ListResponse;
+import io.github.dbmdz.metadata.server.backend.api.repository.exceptions.RepositoryException;
+import io.github.dbmdz.metadata.server.backend.api.repository.identifiable.IdentifierRepository;
+import io.github.dbmdz.metadata.server.backend.api.repository.identifiable.alias.UrlAliasRepository;
+import io.github.dbmdz.metadata.server.backend.api.repository.identifiable.entity.work.DigipressManifestationRepository;
+import io.github.dbmdz.metadata.server.backend.impl.jdbi.identifiable.entity.EntityRepositoryImpl;
+import io.github.dbmdz.metadata.server.backend.impl.jdbi.identifiable.entity.agent.AgentRepositoryImpl;
+import io.github.dbmdz.metadata.server.backend.impl.jdbi.identifiable.entity.geo.location.HumanSettlementRepositoryImpl;
+import io.github.dbmdz.metadata.server.backend.impl.jdbi.type.LocalDateRangeMapper;
+import io.github.dbmdz.metadata.server.backend.impl.jdbi.type.MainSubTypeMapper.ExpressionTypeMapper;
+import io.github.dbmdz.metadata.server.backend.impl.jdbi.type.TitleMapper;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+import org.jdbi.v3.core.Jdbi;
+import org.jdbi.v3.core.JdbiException;
+import org.jdbi.v3.core.statement.StatementException;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public class DigipressManifestationRepositoryImpl extends ManifestationRepositoryImpl
+ implements DigipressManifestationRepository {
+
+ public DigipressManifestationRepositoryImpl(
+ Jdbi jdbi,
+ CudamiConfig cudamiConfig,
+ IdentifierRepository identifierRepository,
+ UrlAliasRepository urlAliasRepository,
+ ExpressionTypeMapper expressionTypeMapper,
+ LocalDateRangeMapper dateRangeMapper,
+ TitleMapper titleMapper,
+ EntityRepositoryImpl entityRepository,
+ AgentRepositoryImpl agentRepository,
+ HumanSettlementRepositoryImpl humanSettlementRepository) {
+ super(
+ jdbi,
+ cudamiConfig,
+ identifierRepository,
+ urlAliasRepository,
+ expressionTypeMapper,
+ dateRangeMapper,
+ titleMapper,
+ entityRepository,
+ agentRepository,
+ humanSettlementRepository);
+ }
+
+ @Override
+ public void refreshTable() {
+ dbi.useHandle(h -> h.execute("refresh materialized view digipress;"));
+ }
+
+ @Override
+ public String getColumnName(String modelProperty) {
+ return switch (modelProperty) {
+ case "lastModified" -> "mf_lastModified";
+ case "identifiableObjectType" -> "mf_identifiableObjectType";
+ case "nameLocalesOfOriginalScripts" -> "mf_nameLocalesOfOriginalScripts";
+ case "identifiers.id" -> "id_id";
+ case "identifiers.namespace" -> "id_namespace";
+ case "expressionTypes",
+ "manifestationType",
+ "manufacturingType",
+ "mediaTypes",
+ "otherLanguages" ->
+ "mf_%s".formatted(modelProperty);
+ default -> super.getColumnName(modelProperty).replace('.', '_');
+ };
+ }
+
+ @Override
+ public ListResponse getNewspapers(ListRequest listRequest)
+ throws RepositoryException {
+ StringBuilder sqlQuery = new StringBuilder("select * from digipress ");
+ Map mappings = new HashMap<>();
+ if (listRequest.hasFiltering()) addFiltering(listRequest.getFiltering(), sqlQuery, mappings);
+ if (listRequest.hasSorting()) addOrderBy(listRequest.getSorting(), sqlQuery);
+
+ try {
+ List results =
+ dbi.withHandle(
+ h ->
+ h.createQuery(sqlQuery.toString())
+ .bindMap(mappings)
+ .reduceRows(this::basicReduceRowsBiConsumer)
+ .collect(Collectors.toList()));
+ return new ListResponse<>(results, listRequest);
+ } catch (StatementException e) {
+ String detailMessage = e.getCause() != null ? e.getCause().getMessage() : e.getMessage();
+ throw new RepositoryException(
+ String.format("The SQL statement is defective: %s", detailMessage), e);
+ } catch (JdbiException e) {
+ throw new RepositoryException(e);
+ }
+ }
+}
diff --git a/metasvc-server/backend-jdbi/src/main/java/io/github/dbmdz/metadata/server/backend/impl/jdbi/identifiable/entity/work/ManifestationRepositoryImpl.java b/metasvc-server/backend-jdbi/src/main/java/io/github/dbmdz/metadata/server/backend/impl/jdbi/identifiable/entity/work/ManifestationRepositoryImpl.java
index 1783df1b1..fc75cc3b5 100644
--- a/metasvc-server/backend-jdbi/src/main/java/io/github/dbmdz/metadata/server/backend/impl/jdbi/identifiable/entity/work/ManifestationRepositoryImpl.java
+++ b/metasvc-server/backend-jdbi/src/main/java/io/github/dbmdz/metadata/server/backend/impl/jdbi/identifiable/entity/work/ManifestationRepositoryImpl.java
@@ -59,12 +59,14 @@
import org.jdbi.v3.core.result.RowView;
import org.jdbi.v3.core.statement.PreparedBatch;
import org.jdbi.v3.core.statement.StatementException;
+import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Repository;
@SuppressFBWarnings(
value = "VA_FORMAT_STRING_USES_NEWLINE",
justification = "Newline is OK in multiline strings")
@Repository
+@Primary
public class ManifestationRepositoryImpl extends EntityRepositoryImpl
implements ManifestationRepository {
@@ -255,13 +257,13 @@ public String getColumnName(String modelProperty) {
case "titles":
case "version":
case "work":
- return modelProperty;
+ return tableAlias + "." + modelProperty;
case "expressionTypes":
case "manifestationType":
case "manufacturingType":
case "mediaTypes":
case "otherLanguages":
- return modelProperty.toLowerCase();
+ return tableAlias + "." + modelProperty.toLowerCase();
default:
return super.getColumnName(modelProperty);
}
diff --git a/metasvc-server/backend-jdbi/src/main/resources/io/github/dbmdz/metadata/server/backend/impl/database/migration/R__materialized_view_digipress.sql b/metasvc-server/backend-jdbi/src/main/resources/io/github/dbmdz/metadata/server/backend/impl/database/migration/R__materialized_view_digipress.sql
new file mode 100644
index 000000000..7085f0f8f
--- /dev/null
+++ b/metasvc-server/backend-jdbi/src/main/resources/io/github/dbmdz/metadata/server/backend/impl/database/migration/R__materialized_view_digipress.sql
@@ -0,0 +1,158 @@
+DROP MATERIALIZED VIEW IF EXISTS digipress;
+
+CREATE MATERIALIZED VIEW digipress AS
+SELECT
+ mf.uuid mf_uuid,
+ mf.created mf_created,
+ mf.last_modified mf_lastModified,
+ mf.description mf_description,
+ mf.identifiable_objecttype mf_identifiableObjectType,
+ mf.identifiable_type mf_type,
+ mf.label mf_label,
+ mf.preview_hints mf_previewImageRenderingHints,
+ mf.custom_attrs mf_customAttributes,
+ mf.navdate mf_navDate,
+ mf.refid mf_refId,
+ mf.notes mf_notes,
+ mf.expressiontypes mf_expressionTypes,
+ mf.language mf_language,
+ mf.manifestationtype mf_manifestationType,
+ mf.manufacturingtype mf_manufacturingType,
+ mf.mediatypes mf_mediaTypes,
+ mf.titles mf_titles,
+ -- work
+ w.uuid wo_uuid,
+ get_identifiers (w.uuid) wo_identifiers,
+ w.label wo_label,
+ w.titles wo_titles,
+ mms.title parent_title,
+ mms.sortKey parent_sortKey,
+ parent.uuid parent_uuid,
+ parent.label parent_label,
+ parent.titles parent_titles,
+ parent.manifestationtype parent_manifestationType,
+ parent.refid parent_refId,
+ parent.notes parent_notes,
+ parent.created parent_created,
+ parent.last_modified parent_lastModified,
+ parent.identifiable_objecttype parent_identifiableObjectType,
+ get_identifiers (parent.uuid) parent_identifiers,
+ -- parent's work
+ parentwork.uuid parentwork_uuid,
+ get_identifiers (parentwork.uuid) parentwork_identifiers,
+ parentwork.label parentwork_label,
+ parentwork.titles parentwork_titles,
+ rel.predicate rel_predicate,
+ rel.sortindex rel_sortindex,
+ rel.additional_predicates rel_additionalPredicates,
+ max(rel.sortindex) OVER (
+ PARTITION BY
+ mf.uuid
+ ) relation_max_sortindex,
+ get_identifiers (e.uuid) e_identifiers,
+ -- entity's name, if any
+ ename.name entity_name,
+ ename.name_locales_original_scripts entity_nameLocalesOfOriginalScripts,
+ e.uuid e_uuid,
+ e.created e_created,
+ e.last_modified e_lastModified,
+ e.description e_description,
+ e.identifiable_objecttype e_identifiableObjectType,
+ e.identifiable_type e_type,
+ e.label e_label,
+ e.preview_hints e_previewImageRenderingHints,
+ e.custom_attrs e_customAttributes,
+ e.navdate e_navDate,
+ e.refid e_refId,
+ e.notes e_notes,
+ mf.publication_info mf_publicationInfo,
+ mf.production_info mf_productionInfo,
+ mf.distribution_info mf_distributionInfo,
+ -- publisher
+ ag.uuid ag_uuid,
+ ag.created ag_created,
+ ag.last_modified ag_lastModified,
+ ag.description ag_description,
+ ag.identifiable_objecttype ag_identifiableObjectType,
+ ag.identifiable_type ag_type,
+ ag.label ag_label,
+ ag.preview_hints ag_previewImageRenderingHints,
+ ag.custom_attrs ag_customAttributes,
+ ag.navdate ag_navDate,
+ ag.refid ag_refId,
+ ag.notes ag_notes,
+ ag.name ag_name,
+ ag.name_locales_original_scripts ag_nameLocalesOfOriginalScripts,
+ h.uuid hs_uuid,
+ h.created hs_created,
+ h.last_modified hs_lastModified,
+ h.description hs_description,
+ h.identifiable_objecttype hs_identifiableObjectType,
+ h.identifiable_type hs_type,
+ h.label hs_label,
+ h.preview_hints hs_previewImageRenderingHints,
+ h.custom_attrs hs_customAttributes,
+ h.navdate hs_navDate,
+ h.refid hs_refId,
+ h.notes hs_notes,
+ h.name hs_name,
+ h.name_locales_original_scripts hs_nameLocalesOfOriginalScripts,
+ h.geolocation_type hs_geoLocationType,
+ h.settlement_type hs_humanSettlementType,
+ get_identifiers (ag.uuid) ag_identifiers,
+ get_identifiers (h.uuid) hs_identifiers,
+ id.uuid id_uuid,
+ id.created id_created,
+ id.last_modified id_lastModified,
+ id.identifiable id_identifiable,
+ id.namespace id_namespace,
+ id.identifier id_id,
+ file.uuid pi_uuid,
+ file.label pi_label,
+ file.filename pi_filename,
+ file.mimetype pi_mimeType,
+ file.uri pi_uri,
+ file.http_base_url pi_httpBaseUrl,
+ ua.uuid ua_uuid,
+ ua.created ua_created,
+ ua.last_modified ua_lastModified,
+ ua.last_published ua_lastPublished,
+ ua.primary ua_primary,
+ ua.slug ua_slug,
+ ua.target_language ua_targetLanguage,
+ ua.target_identifiable_objecttype uaidf_identifiableObjectType,
+ ua.target_identifiable_type uaidf_identifiableType,
+ ua.target_uuid uaidf_uuid,
+ uawebs.uuid uawebs_uuid,
+ uawebs.label uawebs_label,
+ uawebs.url uawebs_url
+FROM
+ (
+ SELECT
+ mf.*
+ FROM
+ manifestations AS mf
+ LEFT JOIN identifiers id ON id.identifiable = mf.uuid
+ WHERE
+ manifestationtype IN ('NEWSPAPER', 'JOURNAL')
+ AND (id.namespace = 'mdz-manifestation-periodical')
+ ) AS mf
+ LEFT JOIN (
+ manifestation_manifestations mms
+ INNER JOIN manifestations parent ON parent.uuid = mms.subject_uuid
+ ) ON mms.object_uuid = mf.uuid
+ LEFT JOIN works parentwork ON parentwork.uuid = parent.work
+ LEFT JOIN (
+ rel_entity_entities rel
+ INNER JOIN entities e ON rel.subject_uuid = e.uuid
+ ) ON rel.object_uuid = mf.uuid
+ -- select the entity's name, if any
+ LEFT JOIN named_entities ename ON ename.uuid = e.uuid
+ LEFT JOIN works w ON w.uuid = mf.work
+ LEFT JOIN agents ag ON ag.uuid = ANY (mf.publishing_info_agent_uuids)
+ LEFT JOIN humansettlements h ON h.uuid = ANY (mf.publishing_info_locations_uuids)
+ LEFT JOIN identifiers AS id ON mf.uuid = id.identifiable
+ LEFT JOIN fileresources_image AS file ON mf.previewfileresource = file.uuid
+ LEFT JOIN url_aliases AS ua ON mf.uuid = ua.target_uuid
+ LEFT JOIN websites AS uawebs ON uawebs.uuid = ua.website_uuid;
+
diff --git a/metasvc-server/backend-lobid/pom.xml b/metasvc-server/backend-lobid/pom.xml
index 18119b963..d30030a23 100644
--- a/metasvc-server/backend-lobid/pom.xml
+++ b/metasvc-server/backend-lobid/pom.xml
@@ -6,7 +6,7 @@
io.github.dbmdz.metadata
metasvc-server
- 9.2.2-SNAPSHOT
+ 9.3.0-SNAPSHOT
Metadata-Service: Repository Server (Backend IMPL External System lobid.org)
diff --git a/metasvc-server/business/pom.xml b/metasvc-server/business/pom.xml
index 359ec884d..cfa525f84 100644
--- a/metasvc-server/business/pom.xml
+++ b/metasvc-server/business/pom.xml
@@ -6,7 +6,7 @@
io.github.dbmdz.metadata
metasvc-server
- 9.2.2-SNAPSHOT
+ 9.3.0-SNAPSHOT
Metadata-Service: Repository Server (Business)
diff --git a/metasvc-server/business/src/main/java/io/github/dbmdz/metadata/server/business/api/service/identifiable/entity/work/DigipressService.java b/metasvc-server/business/src/main/java/io/github/dbmdz/metadata/server/business/api/service/identifiable/entity/work/DigipressService.java
new file mode 100644
index 000000000..320d52e30
--- /dev/null
+++ b/metasvc-server/business/src/main/java/io/github/dbmdz/metadata/server/business/api/service/identifiable/entity/work/DigipressService.java
@@ -0,0 +1,14 @@
+package io.github.dbmdz.metadata.server.business.api.service.identifiable.entity.work;
+
+import de.digitalcollections.model.identifiable.entity.manifestation.Manifestation;
+import de.digitalcollections.model.list.ListRequest;
+import de.digitalcollections.model.list.ListResponse;
+import io.github.dbmdz.metadata.server.backend.api.repository.exceptions.RepositoryException;
+
+public interface DigipressService {
+
+ void refreshTable();
+
+ ListResponse getNewspapers(ListRequest listRequest)
+ throws RepositoryException;
+}
diff --git a/metasvc-server/business/src/main/java/io/github/dbmdz/metadata/server/business/impl/service/identifiable/entity/work/DigipressServiceImpl.java b/metasvc-server/business/src/main/java/io/github/dbmdz/metadata/server/business/impl/service/identifiable/entity/work/DigipressServiceImpl.java
new file mode 100644
index 000000000..b8ad51064
--- /dev/null
+++ b/metasvc-server/business/src/main/java/io/github/dbmdz/metadata/server/business/impl/service/identifiable/entity/work/DigipressServiceImpl.java
@@ -0,0 +1,30 @@
+package io.github.dbmdz.metadata.server.business.impl.service.identifiable.entity.work;
+
+import de.digitalcollections.model.identifiable.entity.manifestation.Manifestation;
+import de.digitalcollections.model.list.ListRequest;
+import de.digitalcollections.model.list.ListResponse;
+import io.github.dbmdz.metadata.server.backend.api.repository.exceptions.RepositoryException;
+import io.github.dbmdz.metadata.server.backend.api.repository.identifiable.entity.work.DigipressManifestationRepository;
+import io.github.dbmdz.metadata.server.business.api.service.identifiable.entity.work.DigipressService;
+import org.springframework.stereotype.Service;
+
+@Service
+public class DigipressServiceImpl implements DigipressService {
+
+ private DigipressManifestationRepository repository;
+
+ public DigipressServiceImpl(DigipressManifestationRepository repository) {
+ this.repository = repository;
+ }
+
+ @Override
+ public void refreshTable() {
+ repository.refreshTable();
+ }
+
+ @Override
+ public ListResponse getNewspapers(ListRequest listRequest)
+ throws RepositoryException {
+ return repository.getNewspapers(listRequest);
+ }
+}
diff --git a/metasvc-server/pom.xml b/metasvc-server/pom.xml
index 6aedc2f0a..97b79f6be 100644
--- a/metasvc-server/pom.xml
+++ b/metasvc-server/pom.xml
@@ -6,7 +6,7 @@
io.github.dbmdz.metadata
metasvc
- 9.2.2-SNAPSHOT
+ 9.3.0-SNAPSHOT
Metadata-Service: Repository Server
diff --git a/metasvc-server/webapp/pom.xml b/metasvc-server/webapp/pom.xml
index ddf1ee0df..d5e7621b2 100644
--- a/metasvc-server/webapp/pom.xml
+++ b/metasvc-server/webapp/pom.xml
@@ -6,7 +6,7 @@
io.github.dbmdz.metadata
metasvc-server
- 9.2.2-SNAPSHOT
+ 9.3.0-SNAPSHOT
Metadata-Service: Repository Server (Webapp)
diff --git a/metasvc-server/webapp/src/main/java/io/github/dbmdz/metadata/server/controller/identifiable/entity/work/DigipressController.java b/metasvc-server/webapp/src/main/java/io/github/dbmdz/metadata/server/controller/identifiable/entity/work/DigipressController.java
new file mode 100644
index 000000000..cfa7b1881
--- /dev/null
+++ b/metasvc-server/webapp/src/main/java/io/github/dbmdz/metadata/server/controller/identifiable/entity/work/DigipressController.java
@@ -0,0 +1,49 @@
+package io.github.dbmdz.metadata.server.controller.identifiable.entity.work;
+
+import de.digitalcollections.model.identifiable.entity.manifestation.Manifestation;
+import de.digitalcollections.model.list.ListRequest;
+import de.digitalcollections.model.list.ListResponse;
+import de.digitalcollections.model.list.filtering.Filtering;
+import de.digitalcollections.model.list.sorting.Order;
+import de.digitalcollections.model.list.sorting.Sorting;
+import io.github.dbmdz.metadata.server.backend.api.repository.exceptions.RepositoryException;
+import io.github.dbmdz.metadata.server.business.api.service.identifiable.entity.work.DigipressService;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import java.util.List;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.ResponseStatus;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@Tag(name = "DigiPress optimised controller")
+public class DigipressController {
+
+ private DigipressService service;
+
+ public DigipressController(DigipressService digipressService) {
+ service = digipressService;
+ }
+
+ @PutMapping(value = "/v6/digipress/refresh")
+ @ResponseStatus(code = HttpStatus.NO_CONTENT)
+ public void refreshTable() {
+ service.refreshTable();
+ }
+
+ @GetMapping(path = "/v6/digipress", produces = MediaType.APPLICATION_JSON_VALUE)
+ @ResponseBody
+ public ListResponse find(
+ @RequestParam(name = "filtering", required = false) Filtering filtering,
+ @RequestParam(name = "sortBy", required = false) List sortBy)
+ throws RepositoryException {
+ ListRequest listRequest = new ListRequest();
+ listRequest.add(filtering);
+ if (sortBy != null && !sortBy.isEmpty()) listRequest.add(new Sorting(sortBy));
+ return service.getNewspapers(listRequest);
+ }
+}
diff --git a/pom.xml b/pom.xml
index c4223c2b2..e00748720 100644
--- a/pom.xml
+++ b/pom.xml
@@ -11,7 +11,7 @@
io.github.dbmdz.metadata
metasvc
- 9.2.2-SNAPSHOT
+ 9.3.0-SNAPSHOT
pom
Metadata-Service