Skip to content

Commit 51795a3

Browse files
committed
Fix translationCache.
1 parent 453b61f commit 51795a3

7 files changed

Lines changed: 16 additions & 69 deletions

File tree

application/src/main/java/org/opentripplanner/gtfs/mapping/TranslationHelper.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ I18NString getTranslation(
157157
hm.put(translation.getLanguage(), translation.getTranslation());
158158
}
159159
}
160-
return TranslatedString.getDeduplicatedI18NString(hm, false);
160+
return TranslatedString.getI18NString(hm, false);
161161
}
162162
return NonLocalizedString.ofNullable(defaultValue);
163163
}

application/src/main/java/org/opentripplanner/netex/mapping/StationMapper.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ private I18NString resolveName(StopPlace stopPlace) {
122122
}
123123
}
124124

125-
name = TranslatedString.getDeduplicatedI18NString(translations, false);
125+
name = TranslatedString.getI18NString(translations, false);
126126
} else {
127127
name = new NonLocalizedString(stopPlace.getName().getValue());
128128
}

application/src/main/java/org/opentripplanner/osm/model/OsmEntity.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -529,10 +529,7 @@ public I18NString getAssumedName() {
529529
return null;
530530
}
531531
if (tags.containsKey("name")) {
532-
return TranslatedString.getDeduplicatedI18NString(
533-
this.generateI18NForPattern("{name}"),
534-
false
535-
);
532+
return TranslatedString.getI18NString(this.generateI18NForPattern("{name}"), false);
536533
}
537534
if (tags.containsKey("otp:route_name")) {
538535
return new NonLocalizedString(tags.get("otp:route_name"));

application/src/main/java/org/opentripplanner/osm/wayproperty/NoteProperties.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ public StreetNoteAndMatcher generateNote(OsmEntity way) {
2828
if (patternMatcher.matcher(notePattern).matches()) {
2929
//This gets language -> translation of notePattern and all tags (which can have translations name:en for example)
3030
Map<String, String> noteText = way.generateI18NForPattern(notePattern);
31-
text = TranslatedString.getDeduplicatedI18NString(noteText, false);
31+
text = TranslatedString.getI18NString(noteText, false);
3232
} else {
3333
text = LocalizedStringMapper.getInstance().map(notePattern, way);
3434
}

application/src/test/java/org/opentripplanner/framework/graphql/GraphQLUtilsTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ void testGetTranslationWithTranslations() {
4848
entry("en", "translationEn"),
4949
entry("fr", frenchTranslation)
5050
);
51-
var translatedString = TranslatedString.getDeduplicatedI18NString(translations, false);
51+
var translatedString = TranslatedString.getI18NString(translations, false);
5252

5353
var translation = GraphQLUtils.getTranslation(translatedString, env);
5454

domain-core/src/main/java/org/opentripplanner/core/model/i18n/TranslatedString.java

Lines changed: 9 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import java.util.Map;
1111
import java.util.Map.Entry;
1212
import java.util.Objects;
13+
import java.util.concurrent.ConcurrentHashMap;
1314

1415
/**
1516
* This is for translated strings for which translations are read from OSM or GTFS alerts.
@@ -24,7 +25,8 @@ public class TranslatedString implements I18NString, Serializable {
2425
* Store all translations, so we don't get memory overhead for identical strings As this is
2526
* static, it isn't serialized when saving the graph.
2627
*/
27-
private static final HashMap<Map<String, String>, I18NString> translationCache = new HashMap<>();
28+
private static final ConcurrentHashMap<Map<String, String>, I18NString> translationCache =
29+
new ConcurrentHashMap<>();
2830

2931
private final Map<String, String> translations = new HashMap<>();
3032

@@ -52,89 +54,37 @@ public static I18NString getI18NString(String untranslated, String... translatio
5254
return getI18NString(map, false);
5355
}
5456

55-
/**
56-
* Gets a deduplicated I18NString. If the translations only have a single value, return a
57-
* NonLocalizedString, otherwise a TranslatedString. The resulting I18NString is interned for
58-
* memory efficiency.
59-
* <p>
60-
* This should be used when calling this method during graph building. This should not be called
61-
* from a real-time updater as this is not thread-safe and may cause a memory leak.
62-
*
63-
* @param translations A Map of languages and translations, a null language is the default
64-
* translation
65-
* @param forceTranslatedString Should the language information be kept, even when only a single
66-
* translation is provided. This is useful when the language
67-
* information is important or is presented to the user.
68-
*/
69-
public static I18NString getDeduplicatedI18NString(
70-
Map<String, String> translations,
71-
boolean forceTranslatedString
72-
) {
73-
return getI18NString(translations, true, forceTranslatedString);
74-
}
75-
76-
/**
77-
* Gets a non-deduplicated I18NString. If the translations only have a single value, return a
78-
* NonLocalizedString, otherwise a TranslatedString. The resulting I18NString is NOT interned.
79-
* <p>
80-
* This should be used from real-time updaters to avoid memory leaks. For graph building, use
81-
* {@link #getDeduplicatedI18NString(Map, boolean)} instead.
82-
*
83-
* @param translations A Map of languages and translations, a null language is the default
84-
* translation
85-
* @param forceTranslatedString Should the language information be kept, even when only a single
86-
* translation is provided. This is useful when the language
87-
* information is important or is presented to the user.
88-
*/
89-
public static I18NString getI18NString(
90-
Map<String, String> translations,
91-
boolean forceTranslatedString
92-
) {
93-
return getI18NString(translations, false, forceTranslatedString);
94-
}
95-
9657
/**
9758
* Gets an I18NString. If the translations only have a single value, return a NonLocalizedString,
9859
* otherwise a TranslatedString
9960
*
10061
* @param translations A Map of languages and translations, a null language is the default
10162
* translation
102-
* @param intern Should the resulting I18NString be interned. This should be used when calling
103-
* this method during graph building. This should not be called from a real-time
104-
* updater as this is not thread-safe and may cause a memory leak.
10563
* @param forceTranslatedString Should the language information be kept, even when only a single
10664
* translation is provided. This is useful when the language
10765
* information is important or is presented to the user.
10866
*/
109-
static I18NString getI18NString(
67+
public static I18NString getI18NString(
11068
Map<String, String> translations,
111-
boolean intern,
11269
boolean forceTranslatedString
11370
) {
11471
if (translations.isEmpty()) {
11572
throw new IllegalArgumentException("At least one translation must be provided");
11673
}
117-
if (translationCache.containsKey(translations)) {
118-
return translationCache.get(translations);
119-
} else {
120-
I18NString ret;
74+
return translationCache.computeIfAbsent(translations, k -> {
12175
// Check if we only have one name, even under multiple languages
12276
boolean allValuesEqual = new HashSet<>(translations.values()).size() == 1;
12377
var firstLanguage = translations.keySet().iterator().next();
12478
boolean onlySingleUntranslatedLanguage =
12579
translations.size() == 1 && (firstLanguage == null || firstLanguage.isBlank());
12680
if (forceTranslatedString && !onlySingleUntranslatedLanguage) {
127-
ret = new TranslatedString(translations);
81+
return new TranslatedString(translations);
12882
} else if (allValuesEqual) {
129-
ret = new NonLocalizedString(translations.values().iterator().next());
83+
return new NonLocalizedString(translations.values().iterator().next());
13084
} else {
131-
ret = new TranslatedString(translations);
132-
}
133-
if (intern) {
134-
translationCache.put(translations, ret);
85+
return new TranslatedString(translations);
13586
}
136-
return ret;
137-
}
87+
});
13888
}
13989

14090
@Override

domain-core/src/test/java/org/opentripplanner/core/model/i18n/TranslatedStringTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ public void testGetI18NString() {
2828
assertTrue(string2 instanceof NonLocalizedString);
2929

3030
translations.put("fi", "Testi");
31-
I18NString string3 = TranslatedString.getDeduplicatedI18NString(translations, false);
31+
I18NString string3 = TranslatedString.getI18NString(translations, false);
3232
assertEquals("Test", string3.toString());
3333
assertEquals("Test", string3.toString(Locale.ENGLISH));
3434
assertEquals("Testi", string3.toString(new Locale("fi")));
@@ -38,7 +38,7 @@ public void testGetI18NString() {
3838
translations2.put(null, "Test");
3939
translations2.put("en", "Test");
4040
translations2.put("fi", "Testi");
41-
I18NString string4 = TranslatedString.getDeduplicatedI18NString(translations2, false);
41+
I18NString string4 = TranslatedString.getI18NString(translations2, false);
4242
assertSame(string3, string4);
4343
}
4444

0 commit comments

Comments
 (0)