Skip to content

Commit 7408173

Browse files
committed
LocaleCompat.forLanguageTag: return Optional if parsing fails
It’s not obvious that the function will fail in some cases and throw an `IllegalArgumentException`. So instead of just failing if parsing fails, return an Optional that all callers have to decide what to do (e.g. the YoutubeExtractor can just ignore the locale in that case, like it does with most other fields in the json if they are unexpected).
1 parent 3402cdb commit 7408173

5 files changed

Lines changed: 40 additions & 21 deletions

File tree

extractor/src/main/java/org/schabi/newpipe/extractor/localization/Localization.java

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,12 @@
1111
import java.util.Locale;
1212
import java.util.Map;
1313
import java.util.Objects;
14+
import java.util.Optional;
1415

1516
import javax.annotation.Nonnull;
1617
import javax.annotation.Nullable;
1718

19+
1820
public class Localization implements Serializable {
1921
public static final Localization DEFAULT = new Localization("en", "GB");
2022

@@ -26,20 +28,28 @@ public class Localization implements Serializable {
2628
/**
2729
* @param localizationCodeList a list of localization code, formatted like {@link
2830
* #getLocalizationCode()}
31+
* @throws IllegalArgumentException If any of the localizationCodeList is formatted incorrectly
32+
* @return list of Localization objects
2933
*/
34+
@Nonnull
3035
public static List<Localization> listFrom(final String... localizationCodeList) {
3136
final List<Localization> toReturn = new ArrayList<>();
3237
for (final String localizationCode : localizationCodeList) {
33-
toReturn.add(fromLocalizationCode(localizationCode));
38+
toReturn.add(fromLocalizationCode(localizationCode)
39+
.orElseThrow(() -> new IllegalArgumentException(
40+
"Not a localization code: " + localizationCode
41+
)));
3442
}
3543
return Collections.unmodifiableList(toReturn);
3644
}
3745

3846
/**
3947
* @param localizationCode a localization code, formatted like {@link #getLocalizationCode()}
48+
* @return A Localization, if the code was valid.
4049
*/
41-
public static Localization fromLocalizationCode(final String localizationCode) {
42-
return fromLocale(LocaleCompat.forLanguageTag(localizationCode));
50+
@Nonnull
51+
public static Optional<Localization> fromLocalizationCode(final String localizationCode) {
52+
return LocaleCompat.forLanguageTag(localizationCode).map(Localization::fromLocale);
4353
}
4454

4555
public Localization(@Nonnull final String languageCode, @Nullable final String countryCode) {
@@ -61,17 +71,15 @@ public String getCountryCode() {
6171
return countryCode == null ? "" : countryCode;
6272
}
6373

64-
public Locale asLocale() {
65-
return new Locale(getLanguageCode(), getCountryCode());
66-
}
67-
6874
public static Localization fromLocale(@Nonnull final Locale locale) {
6975
return new Localization(locale.getLanguage(), locale.getCountry());
7076
}
7177

7278
/**
7379
* Return a formatted string in the form of: {@code language-Country}, or
7480
* just {@code language} if country is {@code null}.
81+
*
82+
* @return A correctly formatted localizationCode for this localization.
7583
*/
7684
public String getLocalizationCode() {
7785
return languageCode + (countryCode == null ? "" : "-" + countryCode);

extractor/src/main/java/org/schabi/newpipe/extractor/services/media_ccc/extractors/MediaCCCStreamExtractor.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,10 @@ public List<AudioStream> getAudioStreams() throws ExtractionException {
130130
// track with multiple languages, so there is no specific language for this stream
131131
// Don't set the audio language in this case
132132
if (language != null && !language.contains("-")) {
133-
builder.setAudioLocale(LocaleCompat.forLanguageTag(language));
133+
builder.setAudioLocale(LocaleCompat.forLanguageTag(language).orElseThrow(() ->
134+
new ExtractionException(
135+
"Cannot convert this language to a locale: " + language)
136+
));
134137
}
135138

136139
// Not checking containsSimilarStream here, since MediaCCC does not provide enough

extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeStreamExtractor.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ public String getTextualUploadDate() throws ParsingException {
190190

191191
try { // Premiered 20 hours ago
192192
final TimeAgoParser timeAgoParser = TimeAgoPatternsManager.getTimeAgoParserFor(
193-
Localization.fromLocalizationCode("en"));
193+
Localization.fromLocalizationCode("en").get());
194194
final OffsetDateTime parsedTime = timeAgoParser.parse(time).offsetDateTime();
195195
return DateTimeFormatter.ISO_LOCAL_DATE.format(parsedTime);
196196
} catch (final Exception ignored) {
@@ -1378,8 +1378,13 @@ private ItagInfo buildAndAddItagInfoToList(
13781378
final int audioTrackIdLastLocaleCharacter = audioTrackId.indexOf(".");
13791379
if (audioTrackIdLastLocaleCharacter != -1) {
13801380
// Audio tracks IDs are in the form LANGUAGE_CODE.TRACK_NUMBER
1381-
itagItem.setAudioLocale(LocaleCompat.forLanguageTag(
1382-
audioTrackId.substring(0, audioTrackIdLastLocaleCharacter)));
1381+
@Nullable final Locale locale =
1382+
LocaleCompat.forLanguageTag(
1383+
audioTrackId.substring(0, audioTrackIdLastLocaleCharacter
1384+
)).orElse(null);
1385+
if (locale != null) {
1386+
itagItem.setAudioLocale(locale);
1387+
}
13831388
}
13841389
itagItem.setAudioTrackType(YoutubeParsingHelper.extractAudioTrackType(streamUrl));
13851390
}

extractor/src/main/java/org/schabi/newpipe/extractor/stream/SubtitlesStream.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,9 @@ private SubtitlesStream(@Nonnull final String id,
231231
final boolean autoGenerated,
232232
@Nullable final String manifestUrl) {
233233
super(id, content, isUrl, mediaFormat, deliveryMethod, manifestUrl);
234-
this.locale = LocaleCompat.forLanguageTag(languageCode);
234+
this.locale = LocaleCompat.forLanguageTag(languageCode).orElseThrow(
235+
() -> new IllegalArgumentException(
236+
"not a valid locale language code: " + languageCode));
235237
this.code = languageCode;
236238
this.format = mediaFormat;
237239
this.autoGenerated = autoGenerated;
Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package org.schabi.newpipe.extractor.utils;
22

33
import java.util.Locale;
4+
import java.util.Optional;
45

56
/**
67
* This class contains a simple implementation of {@link Locale#forLanguageTag(String)} for Android
@@ -15,29 +16,29 @@ private LocaleCompat() {
1516

1617
// Source: The AndroidX LocaleListCompat class's private forLanguageTagCompat() method.
1718
// Use Locale.forLanguageTag() on Android API level >= 21 / Java instead.
18-
public static Locale forLanguageTag(final String str) {
19+
public static Optional<Locale> forLanguageTag(final String str) {
1920
if (str.contains("-")) {
2021
final String[] args = str.split("-", -1);
2122
if (args.length > 2) {
22-
return new Locale(args[0], args[1], args[2]);
23+
return Optional.of(new Locale(args[0], args[1], args[2]));
2324
} else if (args.length > 1) {
24-
return new Locale(args[0], args[1]);
25+
return Optional.of(new Locale(args[0], args[1]));
2526
} else if (args.length == 1) {
26-
return new Locale(args[0]);
27+
return Optional.of(new Locale(args[0]));
2728
}
2829
} else if (str.contains("_")) {
2930
final String[] args = str.split("_", -1);
3031
if (args.length > 2) {
31-
return new Locale(args[0], args[1], args[2]);
32+
return Optional.of(new Locale(args[0], args[1], args[2]));
3233
} else if (args.length > 1) {
33-
return new Locale(args[0], args[1]);
34+
return Optional.of(new Locale(args[0], args[1]));
3435
} else if (args.length == 1) {
35-
return new Locale(args[0]);
36+
return Optional.of(new Locale(args[0]));
3637
}
3738
} else {
38-
return new Locale(str);
39+
return Optional.of(new Locale(str));
3940
}
4041

41-
throw new IllegalArgumentException("Can not parse language tag: [" + str + "]");
42+
return Optional.empty();
4243
}
4344
}

0 commit comments

Comments
 (0)