Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package de.mediathekview.mserver.base.utils;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;

public final class SentenceShortener {
private static final Pattern WHITESPACE_REGEX = Pattern.compile("\\s+");
private static final Pattern SENTENCE_BOUNDARY_REGEX = Pattern.compile("(?<=[.!?])\\s+");
private static final String SHORTENING_SUFFIX = "...";

private SentenceShortener() {
}

/**
* Shortens text to a target length while preserving complete sentences.
*
* <p>Whitespace is normalized before shortening. If the text is already within the target
* length, the normalized text is returned unchanged. If adding the next sentence would exceed
* {@code targetLength + marginLength}, that sentence is omitted and {@code ...} is appended to
* the returned text. If the first sentence alone is already longer than the limit, it is kept
* whole.
*
* @param text the text to shorten; may be {@code null}
* @param targetLength the preferred target length; must be positive
* @param marginLength the allowed soft overflow beyond the target; must not be negative
* @return the shortened text, or {@code null} if the input is {@code null} or blank
* @throws IllegalArgumentException if {@code targetLength <= 0} or {@code marginLength < 0}
*/
public static String shorten(String text, int targetLength, int marginLength) {
if (targetLength <= 0) {
throw new IllegalArgumentException("targetLength must be positive");
}
if (marginLength < 0) {
throw new IllegalArgumentException("marginLength must not be negative");
}

String normalized = normalize(text);
if (normalized == null || normalized.length() <= targetLength) {
return normalized;
}

int softLimit = targetLength + marginLength;
String[] rawSentences = SENTENCE_BOUNDARY_REGEX.split(normalized);
List<String> sentences = new ArrayList<>();
for (String rawSentence : rawSentences) {
String sentence = rawSentence.trim();
if (!sentence.isEmpty()) {
sentences.add(sentence);
}
}
if (sentences.isEmpty()) {
return normalized;
}

List<String> selectedSentences = new ArrayList<>();
int currentLength = 0;
for (String sentence : sentences) {
int candidateLength = selectedSentences.isEmpty()
? sentence.length()
: currentLength + 1 + sentence.length();
if (candidateLength > softLimit) {
break;
}
selectedSentences.add(sentence);
currentLength = candidateLength;
}

if (!selectedSentences.isEmpty()) {
String shortened = String.join(" ", selectedSentences);
return selectedSentences.size() < sentences.size()
? shortened + SHORTENING_SUFFIX
: shortened;
}
return sentences.size() > 1
? sentences.getFirst() + SHORTENING_SUFFIX
: sentences.getFirst();
}

/**
* Shortens text to a target length without any soft overflow margin.
*
* @param text the text to shorten; may be {@code null}
* @param targetLength the preferred target length; must be positive
* @return the shortened text, or {@code null} if the input is {@code null} or blank
* @throws IllegalArgumentException if {@code targetLength <= 0}
*/
public static String shorten(String text, int targetLength) {
return shorten(text, targetLength, 0);
}

/**
* Normalizes whitespace and trims a text value.
*
* @param text the text to normalize; may be {@code null}
* @return the normalized text, or {@code null} if the input is {@code null} or blank
*/
public static String normalize(String text) {
if (text == null) {
return null;
}
String normalized = WHITESPACE_REGEX.matcher(text).replaceAll(" ").trim();
return normalized.isEmpty() ? null : normalized;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public class TextCleaner {
private static final String CARRIAGE_RETURN = "\r";
private static final String NO_BREAK_SPACE = "\u00a0";
private static final int MAX_BESCHREIBUNG = 400;
private static final int MAX_BESCHREIBUNG_MARGIN_LENGTH = 40;
private static final String[] GERMAN_GEOBLOCKING_TEXTS = {
"+++ Aus rechtlichen Gründen ist der Film nur innerhalb von Deutschland abrufbar. +++",
"+++ Aus rechtlichen Gründen ist diese Sendung nur innerhalb von Deutschland abrufbar. +++",
Expand Down Expand Up @@ -64,10 +65,7 @@ private static String cleanGeoBlockingTexts(final String text) {
}

private static String shortenBeschreibung(final String text) {
if (text.length() > MAX_BESCHREIBUNG) {
return text.substring(0, MAX_BESCHREIBUNG) + "\n.....";
}
return text;
return SentenceShortener.shorten(text, MAX_BESCHREIBUNG, MAX_BESCHREIBUNG_MARGIN_LENGTH);
}

private static String beschreibungCleanUp(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ public static Collection<Object[]> data() {
/*jsonFile*/ "/ard/ard_item_DGS_UT_AD.json",
/*topic*/ "Tatort",
/*title*/ "Der Fluch des Geldes",
/*description*/ "Spielfilm Deutschland 2024 +++ \"Der Fluch des Geldes\" beginnt da, wo \"Die Kälte der Erde\" endete. Die Hauptkommissare streiten sich, denn Leo Hölzer musste entdecken, dass sein Partner Adam Schürk im Besitz der Beute aus einem Bankraub seines verstorbenen Vaters ist. +++ Mit Vladimir Burlakov, Daniel Sträßer, Susanne Bormann, Omar El-Saeidi, Jasmina Al Zihairi u.a. | Buch: Hendrik Hölzemann \n.....",
/*description*/ "Spielfilm Deutschland 2024 +++ \"Der Fluch des Geldes\" beginnt da, wo \"Die Kälte der Erde\" endete. Die Hauptkommissare streiten sich, denn Leo Hölzer musste entdecken, dass sein Partner Adam Schürk im Besitz der Beute aus einem Bankraub seines verstorbenen Vaters ist. +++ Mit Vladimir Burlakov, Daniel Sträßer, Susanne Bormann, Omar El-Saeidi, Jasmina Al Zihairi u.a. | Buch: Hendrik Hölzemann | Regie: Christian Theede",
/*date*/ LocalDateTime.parse("2024-01-28T20:15"),
/*duration*/ Duration.parse("PT1H28M33S"),
/*small*/ "https://pd-videos.daserste.de/int/2024/01/18/3322bac1-6935-4101-8e41-380d70eff67e/JOB_430813_sendeton_640x360-50p-1200kbit.mp4",
Expand Down Expand Up @@ -153,7 +153,7 @@ public static Collection<Object[]> data() {
/*jsonFile*/ "/ard/ard_item_STD_DasErste.json",
/*topic*/ "tagesschau",
/*title*/ "tagesschau 11:10 Uhr, 01.05.2024",
/*description*/ "Bundesweit Kundgebungen zum Tag der Arbeit für bessere Arbeitsbedingungen, Bereits erste Demonstrationen in Berlin und Hamburg, Polizei in Georgiens Hauptstadt Tiflis geht massiv gegen pro-europäische Demonstranten vor, US-Einsatzkräfte räumen mit Großaufgebot besetztes Gebäude der Columbia Universität in New York, US-Bestsellerautor Paul Auster stirbt im Alter von 77 Jahren, Walpurgisnacht im Har\n.....",
/*description*/ "Bundesweit Kundgebungen zum Tag der Arbeit für bessere Arbeitsbedingungen, Bereits erste Demonstrationen in Berlin und Hamburg, Polizei in Georgiens Hauptstadt Tiflis geht massiv gegen pro-europäische Demonstranten vor, US-Einsatzkräfte räumen mit Großaufgebot besetztes Gebäude der Columbia Universität in New York, US-Bestsellerautor Paul Auster stirbt im Alter von 77 Jahren, Walpurgisnacht im Harz, Das Wetter",
/*date*/ LocalDateTime.parse("2024-05-01T11:10"),
/*duration*/ Duration.parse("PT5M6S"),
/*small*/ "https://media.tagesschau.de/video/2024/0501/TV-20240501-1117-3700.webm.h264.mp4",
Expand Down Expand Up @@ -213,7 +213,7 @@ public static Collection<Object[]> data() {
/*jsonFile*/ "/ard/ard_item_STD_ONE.json",
/*topic*/ "Murdoch Mysteries",
/*title*/ "Folge 4: Geisterstunde (S01/E04) (Originalversion)",
/*description*/ "Murdoch schließt sich mit seinem Helden Arthur Conan Doyle zusammen, um einen Mord aufzuklären, der während einer Séance unter der Leitung des Mediums Sarah Pensall aufgedeckt wurde. Es scheint, dass das Opfer Ida Winston, Mitglied einer paranormalen Wächtergruppe, nicht von Sarahs Fähigkeiten überzeugt war. Murdoch fragt sich, ob Sarah Ida getötet hat, weil sie kurz davorstand, als Betrügerin ent\n.....",
/*description*/ "Murdoch schließt sich mit seinem Helden Arthur Conan Doyle zusammen, um einen Mord aufzuklären, der während einer Séance unter der Leitung des Mediums Sarah Pensall aufgedeckt wurde. Es scheint, dass das Opfer Ida Winston, Mitglied einer paranormalen Wächtergruppe, nicht von Sarahs Fähigkeiten überzeugt war. Murdoch fragt sich, ob Sarah Ida getötet hat, weil sie kurz davorstand, als Betrügerin entlarvt zu werden.",
/*date*/ LocalDateTime.parse("2024-05-01T04:15"),
/*duration*/ Duration.parse("PT46M4S"),
/*small*/ "https://wdrmedien-a.akamaihd.net/medp/ondemand/de/fsk12/310/3106351/3106351_57089636.mp4",
Expand All @@ -233,7 +233,7 @@ public static Collection<Object[]> data() {
/*jsonFile*/ "/ard/ard_item_STD_RBB.json",
/*topic*/ "Blue Moon",
/*title*/ "Blue Moon vom 30.04.2024",
/*description*/ "Den Rucksack auskippen, bloßstellende Fotos posten oder Beleidigungen nachrufen - fast jedes sechste Schulkind ist bei uns von Mobbing betroffen. Aber auch im Büro, an der Uni oder im Verein gibt es Mobbing! Diese Woche sprechen wir bei Fritz über das Thema Mobbing, alle Inhalte und Hilfsangebote findet ihr hier: fritz.de/mobbing. Claudia Kamieth will deshalb heute im Blue Moon von euch wissen: Wu\n.....",
/*description*/ "Den Rucksack auskippen, bloßstellende Fotos posten oder Beleidigungen nachrufen - fast jedes sechste Schulkind ist bei uns von Mobbing betroffen. Aber auch im Büro, an der Uni oder im Verein gibt es Mobbing! Diese Woche sprechen wir bei Fritz über das Thema Mobbing, alle Inhalte und Hilfsangebote findet ihr hier: fritz.de/mobbing....",
/*date*/ LocalDateTime.parse("2024-04-30T22:15"),
/*duration*/ Duration.parse("PT1H43M15S"),
/*small*/ "https://rbbmediapmdp-a.akamaihd.net/content/dd/f9/ddf9c4f0-2da1-45b9-812f-873f213ccbd5/eb2ed184-078d-11ef-b0da-02420a000df3_hd1080-avc360.mp4",
Expand All @@ -253,7 +253,7 @@ public static Collection<Object[]> data() {
/*jsonFile*/ "/ard/ard_item_STD_AD_DasErste.json",
/*topic*/ "Mord mit Aussicht",
/*title*/ "Folge 3: Die Bestechlichen (S05/E03)",
/*description*/ "Marie zögert noch bei Gisberts Angebot, zu ihm auf den Schweine-Hof zu ziehen. Willkommene Ablenkung bietet Marie eine Leiche im Heuballen auf Müller Schlichtings Wiese. Der Tote ist Albert Appel, der mit seinem Bruder Kai einen Bauernhof betreibt und außerdem Schiedsrichter der Regionalliga ist. Die Ermittlungen führen in die Welt des Fußballs und zweier rivalisierender Clubs. Das Auftauchen ein\n.....",
/*description*/ "Marie zögert noch bei Gisberts Angebot, zu ihm auf den Schweine-Hof zu ziehen. Willkommene Ablenkung bietet Marie eine Leiche im Heuballen auf Müller Schlichtings Wiese. Der Tote ist Albert Appel, der mit seinem Bruder Kai einen Bauernhof betreibt und außerdem Schiedsrichter der Regionalliga ist. Die Ermittlungen führen in die Welt des Fußballs und zweier rivalisierender Clubs....",
/*date*/ LocalDateTime.parse("2024-04-30T20:15"),
/*duration*/ Duration.parse("PT47M20S"),
/*small*/ "https://wdrmedien-a.akamaihd.net/medp/ondemand/weltweit/fsk12/310/3101569/3101569_56955169.mp4",
Expand All @@ -273,7 +273,7 @@ public static Collection<Object[]> data() {
/*jsonFile*/ "/ard/ard_item_STD_AD_MDR.json",
/*topic*/ "Auf schmaler Spur",
/*title*/ "Reichsbahn-Oldies im Trend",
/*description*/ "Mit gerade mal 27 Jahren ist Tobias Sambill Geschäftsführer des „Salzland Railservice“ in Bernburg. Seine Geschäftsidee: Er betreibt Güterverkehr mit alten Reichsbahnloks und ist ganz verrückt nach „Ludmilla“, Baujahr 1974, 3.000 PS Leistung. Ludmilla ist der Spitzname für Dieselloks der Baureihe 130, die ab 1970 aus der Sowjetunion zur Reichsbahn kamen. Auch in Löbau ist der Nachwuchs schon in d\n.....",
/*description*/ "Mit gerade mal 27 Jahren ist Tobias Sambill Geschäftsführer des „Salzland Railservice“ in Bernburg. Seine Geschäftsidee: Er betreibt Güterverkehr mit alten Reichsbahnloks und ist ganz verrückt nach „Ludmilla“, Baujahr 1974, 3.000 PS Leistung. Ludmilla ist der Spitzname für Dieselloks der Baureihe 130, die ab 1970 aus der Sowjetunion zur Reichsbahn kamen. Auch in Löbau ist der Nachwuchs schon in der Verantwortung....",
/*date*/ LocalDateTime.parse("2024-05-01T13:20"),
/*duration*/ Duration.parse("PT29M31S"),
/*small*/ "https://odgeomdr-a.akamaihd.net/mp4dyn2/a/FCMS-a66d00f7-05d6-4280-8dbe-9c81a47c8667-41dd60577440_a6.mp4",
Expand Down Expand Up @@ -313,7 +313,7 @@ public static Collection<Object[]> data() {
/*jsonFile*/ "/ard/ard_item_ignore_OV.json",
/*topic*/ "You shall not lie - Tödliche Geheimnisse",
/*title*/ "Folge 4: Der Verrat (S01/E04)",
/*description*/ "Zwischen Macarena und Iván, der jetzt von ihrer Schwangerschaft weiß, kommt es zu einer dramatischen Auseinandersetzung auf See. Erschöpft schwimmt der 18-Jährige an Land und beschuldigt sie, ihn vom Boot gestoßen zu haben. Die Lehrerin muss nun nicht nur die Folgen ihres Seitensprungs fürchten, sondern auch eine Anzeige wegen versuchten Totschlags. +++ Sechsteilige Thrillerserie, Spanien 2021\n.....",
/*description*/ "Zwischen Macarena und Iván, der jetzt von ihrer Schwangerschaft weiß, kommt es zu einer dramatischen Auseinandersetzung auf See. Erschöpft schwimmt der 18-Jährige an Land und beschuldigt sie, ihn vom Boot gestoßen zu haben. Die Lehrerin muss nun nicht nur die Folgen ihres Seitensprungs fürchten, sondern auch eine Anzeige wegen versuchten Totschlags....",
/*date*/ LocalDateTime.parse("2022-10-15T02:50"),
/*duration*/ Duration.parse("PT42M18S"),
/*small*/ "https://pd-videos.daserste.de/de/2022/10/11/1cb6c5d8-c0f4-4868-ac42-2a06b7a3381f/JOB_461836_sendeton_640x360-50p-1200kbit.mp4",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ public static Collection<Object[]> data() {
),
/*topic*/ "Fickt euch!",
/*title*/ "Keine Chance für Smegma! Intimhygiene für Jungs I Fickt euch - Ist doch nur Sex",
/*description*/ "Den Penis richtig waschen ist ganz einfach! Was ihr beachten müsst, um Infektionen und unangenehme Gerüche zu vermeiden, erfahrt ihr im Video. Du willst mehr? Dann abonniere meinen Kanal: https://www.youtube.com/channel/UC3ZkjIfabQzVypsQBd9-AIQ?sub_confirmation=1Fickt euch! bei Facebook: http://www.facebook.com/istdochnursexFickt euch! bei Instagram: http://www.instagram.com/istdochnursexFickt euc\n.....",
/*description*/ "Den Penis richtig waschen ist ganz einfach! Was ihr beachten müsst, um Infektionen und unangenehme Gerüche zu vermeiden, erfahrt ihr im Video. Du willst mehr? Dann abonniere meinen Kanal: https://www.youtube.com/channel/UC3ZkjIfabQzVypsQBd9-AIQ?sub_confirmation=1Fickt euch! bei Facebook: http://www.facebook.com/istdochnursexFickt euch! bei Instagram: http://www.instagram.com/istdochnursexFickt euch! bei Snapchat: @istdochnursex",
/*date*/ LocalDateTime.parse("2016-12-13T15:00"),
/*duration*/ Duration.parse("PT3M5S"),
/*small*/ "http://localhost:50998/22679/files/21/01/30/2678992/22679-jqh9gFKRm8YDnC2.ism/22679-jqh9gFKRm8YDnC2-audio=152016-video=771000.m3u8",
Expand Down
Loading
Loading