diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b1362abe..6107541f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -4,7 +4,7 @@ on: push jobs: build: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v2 - name: Set up JDK 1.8 diff --git a/.gitignore b/.gitignore index 173328b5..e2e15703 100644 --- a/.gitignore +++ b/.gitignore @@ -24,3 +24,5 @@ RPB-Export_HBZ_ZSS.txt conf/RPBEXP/*.ZIP conf/strapi-export.tar.gz nohup.out* +conf/*.ndjson +conf/*.zip diff --git a/app/controllers/nwbib/Application.java b/app/controllers/nwbib/Application.java index 089db9a5..b3e5a74f 100644 --- a/app/controllers/nwbib/Application.java +++ b/app/controllers/nwbib/Application.java @@ -259,7 +259,8 @@ public static Promise search(final String q, final String person, response().setHeader("Pragma", "no-cache"); response().setHeader("Expires", "0"); } - String cacheId = String.format("%s-%s", uuid, request().uri()); + String cacheId = request().queryString().isEmpty() ? request().uri() + : String.format("%s-%s", uuid, request().uri()); @SuppressWarnings("unchecked") Promise cachedResult = (Promise) Cache.get(cacheId); if (cachedResult != null) @@ -907,7 +908,7 @@ public static Promise showStars(String format, String ids) { } public static Promise showSw(String rpbId) { - String strapiUrl = "https://rpb-cms.lobid.org/admin/content-manager/collectionType/" + String strapiUrl = "https://rpb-cms.lobid.org/admin/content-manager/collection-types/" + "api::rpb-authority.rpb-authority?filters[$and][0][rpbId][$eq]="; return Promise.pure(seeOther(strapiUrl + rpbId)); } @@ -950,19 +951,43 @@ private static List starredIds() { } public static Promise put(String id, String secret) throws FileNotFoundException, RecognitionException, IOException { - File input = new File("conf/output/test-output-strapi.json"); - File output = new File("conf/output/test-output-0.json"); - Files.write(Paths.get(input.getAbsolutePath()), request().body().asJson().toString().getBytes(Charsets.UTF_8)); - ETL.main(new String[] {"conf/rpb-test-titel-to-lobid.flux"}); - String result = Files.readAllLines(Paths.get(output.getAbsolutePath())).stream().collect(Collectors.joining("\n")); boolean authorized = !secret.trim().isEmpty() && secret.equals(CONFIG.getString("secret")); if (authorized) { - String url = "http://weywot3:9200/resources-rpb-test/resource/" - + URLEncoder.encode("https://lobid.org/resources/" + id, "UTF-8"); - WSRequest request = WS.url(url).setHeader("Content-Type", "application/json"); - return request.put(result).map(response -> status(response.getStatus(), response.getBody())); + return transformAndIndex(id, request().body().asJson()); + } else { + return Promise.pure(unauthorized(secret)); + } + } + + public static Promise delete(String id, String secret) throws FileNotFoundException, RecognitionException, IOException { + boolean authorized = !secret.trim().isEmpty() && secret.equals(CONFIG.getString("secret")); + if (authorized) { + return deleteFromIndex(id); } else { - return Promise.pure(unauthorized()); + return Promise.pure(unauthorized(secret)); } } + + private static Promise deleteFromIndex(String id) throws UnsupportedEncodingException { + Cache.remove(String.format("/%s", id)); + WSRequest request = WS.url(elasticsearchUrl(id)).setHeader("Content-Type", "application/json"); + return request.delete().map(response -> status(response.getStatus(), response.getBody())); + } + + private static Promise transformAndIndex(String id, JsonNode jsonBody) + throws IOException, FileNotFoundException, RecognitionException, UnsupportedEncodingException { + File input = new File("conf/output/test-output-strapi.json"); + File output = new File("conf/output/test-output-0.json"); + Files.write(Paths.get(input.getAbsolutePath()), jsonBody.toString().getBytes(Charsets.UTF_8)); + ETL.main(new String[] {"conf/rpb-test-titel-to-lobid.flux"}); + String result = Files.readAllLines(Paths.get(output.getAbsolutePath())).stream().collect(Collectors.joining("\n")); + Cache.remove(String.format("/%s", id)); + WSRequest request = WS.url(elasticsearchUrl(id)).setHeader("Content-Type", "application/json"); + return request.put(result).map(response -> status(response.getStatus(), response.getBody())); + } + + private static String elasticsearchUrl(String id) throws UnsupportedEncodingException { + return "http://weywot3:9200/resources-rpb-test/resource/" + + URLEncoder.encode("https://lobid.org/resources/" + id, "UTF-8"); + } } diff --git a/app/controllers/nwbib/Lobid.java b/app/controllers/nwbib/Lobid.java index e3209a7c..0cfab6a0 100644 --- a/app/controllers/nwbib/Lobid.java +++ b/app/controllers/nwbib/Lobid.java @@ -678,6 +678,24 @@ private static String locationPolygon(String location) { return location.contains("|") ? location.split("\\|")[1] : location; } + /** + * @param doc The result JSON doc + * @return A mapping of item IDs (URIs) to item details (JSON strings) + */ + public static Map itemDetails(String doc) { + JsonNode items = Json.parse(doc).findValue("hasItem"); + Map result = new HashMap<>(); + if (items != null && (items.isArray() || items.isTextual())) { + Iterator elements = + items.isArray() ? items.elements() : Arrays.asList(items).iterator(); + while (elements.hasNext()) { + JsonNode nextItem = elements.next(); + result.put(nextItem.get("id").asText(), nextItem.toString()); + } + } + return result; + } + /** * @param doc The result JSON doc * @return A mapping of ISILs to item URIs diff --git a/app/rpb/ETL.java b/app/rpb/ETL.java index dcc9d184..d8c38ec9 100644 --- a/app/rpb/ETL.java +++ b/app/rpb/ETL.java @@ -5,6 +5,7 @@ import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; +import java.io.InputStream; import java.util.Arrays; import java.util.HashMap; import java.util.Map; @@ -47,7 +48,9 @@ public static void main(final String[] args) throws FileNotFoundException, Recog } vars.put(matcher.group(1), matcher.group(2)); } - FluxCompiler.compile(ResourceUtil.getStream(fluxFile), vars).start(); + try (InputStream stream = ResourceUtil.getStream(fluxFile)) { + FluxCompiler.compile(stream, vars).start(); + } } } } diff --git a/app/views/TableRow.java b/app/views/TableRow.java index cd3fbc35..de0672b5 100644 --- a/app/views/TableRow.java +++ b/app/views/TableRow.java @@ -107,16 +107,18 @@ public String process(JsonNode doc, String property, String param, private String label(JsonNode doc, String value, List properties) { List results = new ArrayList<>(); List resultValues = labelsFor(doc, value, properties); + JsonNode labelNode = doc.get(properties.get(0)).iterator().next().get("label"); for (int i = 0; i < resultValues.size(); i++) { String currentValue = resultValues.get(i); String[] refAndLabel = refAndLabel(properties.get(i), currentValue, Optional.empty()); + String label = labelNode != null ? labelNode.textValue() : refAndLabel[1]; String result = properties.get(i).equals("numbering") || value.equals("--") ? currentValue : String.format( "%s", - refAndLabel[0], refAndLabel[1]); + refAndLabel[0], label); results.add(result.replace("Band", "").trim()); } return results.stream().collect(Collectors.joining(", Band ")); @@ -215,7 +217,9 @@ String[] refAndLabel(String property, String value, if ((property.equals("containedIn") || property.equals("hasPart") || property.equals("isPartOf") || property.equals("hasSuperordinate") || property.equals("bibliographicCitation")) && value.contains("lobid.org")) { - return new String[] { value, Lobid.resourceLabel(value) }; + return new String[] { value.matches(".*?[as]\\d+.*|.*?\\d{3}[a-z]\\d+.*") // rpbId + ? value.replace("https://lobid.org/resources/", "/") + : value, Lobid.resourceLabel(value) }; } String label = labels.isPresent() && labels.get().size() > 0 ? labels.get().get(0) diff --git a/app/views/details.scala.html b/app/views/details.scala.html index 372d905b..72ac4def 100644 --- a/app/views/details.scala.html +++ b/app/views/details.scala.html @@ -13,6 +13,10 @@ @import play.mvc.Controller.session @import play.cache.Cache +@idAndLabelLink(e: JsValue) = { + @((e\"label").asOpt[String].getOrElse("--")) +} + @pageLink(last: Seq[String], key: String, label: String, tip: String) = { @defining((last.indexOf(session(key))-1,last.indexOf(session(key))+1)) { case (prev,next) =>
  • @@ -66,9 +70,9 @@ *@ @tags.search_form(q)
    - @defining(Lobid.items(doc.toString)) { items => - @defining(!(doc\\"containedIn").isEmpty && (doc\"type").toString.contains("Article")){superordination => -
    + @defining((Lobid.items(doc.toString), Lobid.itemDetails(doc.toString))) { case (items, itemDetails) => + @defining(items.isEmpty && !(doc\\"containedIn").isEmpty && (doc\"type").toString.contains("Article")){superordination => +
    @defining((doc\"rpbId").asOpt[String].getOrElse(q)){ id =>
    @tags.star_button(id) Titeldetails: @@ -80,6 +84,45 @@ }
    + @if(!items.isEmpty || doc.toString.contains("fulltextOnline") || superordination){ +
    +
    + @if(doc.toString.contains("fulltextOnline")){ +
    Online-Ressource:
    +
    + + + + + + @result_field("Link", "fulltextOnline", doc, TableRow.LINKS) +
    +
    + } + @if(superordination){ +
    Bestandsangaben:
    +
    + + + + + + + + + +
    Zum Bestand siehe:@idAndLabelLink((doc\"containedIn").as[Seq[JsValue]].head)
    +
    + } + @if(!superordination && !items.isEmpty && !doc.toString.contains("fulltextOnline")){ + @defining(items.size){num => +
    Bestand in @num Bibliothek@if(num>1){en}:
    + } +
    @tags.items_map(items, itemDetails)
    + } +
    +
    + } } }
    diff --git a/app/views/index.scala.html b/app/views/index.scala.html index 2456484b..bf6078a7 100644 --- a/app/views/index.scala.html +++ b/app/views/index.scala.html @@ -38,8 +38,8 @@

    Die Rheinland-Pfälzische Bibliographie (RPB) ist eine regionale Literaturdokumentation des Landes Rheinland-Pfalz, die seit 1991 im Auftrag des damaligen - Ministeriums für Wissenschaft und Weiterbildung erstellt wird. Sie erfasst Bücher, Aufsätze aus Zeitschriften, Jahrbüchern, Tages- und Wochenzeitungen sowie - Einzelbeiträge aus Sammelwerken. + Ministeriums für Wissenschaft und Weiterbildung erstellt wird. Sie erfasst Literaturnachweise von Büchern, Aufsätzen aus Zeitschriften, Jahrbüchern, Tages- + und Wochenzeitungen sowie Einzelbeiträgen aus Sammelwerken.

    Die Bibliographie wird von Mitarbeitern des Landesbibliothekszentrums an den Standorten Speyer und Koblenz sowie den wissenschaftlichen Stadtbibliotheken in @@ -48,6 +48,10 @@ erfasst. Die Rheinische Landesbibliothek des lbz führt das Titelmaterial redaktionell zusammen und betreut mit dem hbz die für die Herstellung der Bibliographie erforderliche Datenverarbeitung.

    +

    + Um an die Artikel oder Bücher selbst heranzukommen, empfiehlt es sich, diese über die eigene Bibliothek vor Ort zu beschaffen (z.B. als Buchfernleihe oder als + Aufsatzbestellung über die Fernleihe). +

    @* diff --git a/app/views/main.scala.html b/app/views/main.scala.html index 183f3afb..77c21759 100644 --- a/app/views/main.scala.html +++ b/app/views/main.scala.html @@ -106,7 +106,7 @@

    Die Rheinland-Pfälzische Bibliographie
    Ein Entwicklungsprojekt v