@@ -39,22 +39,24 @@ public class FakeValuesService {
39
39
private static final Logger LOG = Logger .getLogger ("faker" );
40
40
private static final Map <Locale , FakeValuesInterface > FAKE_VALUES_CACHE = new HashMap <>();
41
41
42
- private final Map <Locale , FakeValuesInterface > fakeValuesInterfaceMap = new HashMap <>();
42
+ private static final Map <Locale , FakeValuesInterface > fakeValuesInterfaceMap = new HashMap <>();
43
+ private static final Locale DEFAULT_LOCALE = Locale .ENGLISH ;
43
44
private final RandomService randomService ;
45
+ private Locale currentLocale ;
44
46
45
- private final List <Locale > localesChain ;
47
+ private final Map < Locale , List <Locale >> locale2localesChain ;
46
48
47
- private final Map <Class <?>, Map <String , Collection <Method >>> class2methodsCache = new IdentityHashMap <>();
48
- private final Map <Class <?>, Constructor <?>> class2constructorCache = new IdentityHashMap <>();
49
+ private static final Map <Class <?>, Map <String , Collection <Method >>> class2methodsCache = new IdentityHashMap <>();
50
+ private static final Map <Class <?>, Constructor <?>> class2constructorCache = new IdentityHashMap <>();
49
51
private final Map <String , Generex > expression2generex = new WeakHashMap <>();
50
- private final Map <String , String > key2Expression = new WeakHashMap <>();
52
+ private final Map <Locale , Map < String , String > > key2Expression = new WeakHashMap <>();
51
53
private final Map <String , String []> args2splittedArgs = new WeakHashMap <>();
52
54
private final Map <String , String []> key2splittedKey = new WeakHashMap <>();
53
55
54
- private final Map <String , Object > key2fetchedObject = new WeakHashMap <>();
56
+ private final Map <Locale , Map < String , Object > > key2fetchedObject = new WeakHashMap <>();
55
57
private final Map <String , String > name2yaml = new WeakHashMap <>();
56
58
57
- private final Map <Class <?>, Map <String , Map <String [], MethodAndCoercedArgs >>> mapOfMethodAndCoercedArgs = new IdentityHashMap <>();
59
+ private static final Map <Class <?>, Map <String , Map <String [], MethodAndCoercedArgs >>> mapOfMethodAndCoercedArgs = new IdentityHashMap <>();
58
60
59
61
private static final Map <String , List <String >> EXPRESSION_2_SPLITTED = new WeakHashMap <>();
60
62
@@ -79,16 +81,23 @@ public FakeValuesService(Locale locale, RandomService randomService) {
79
81
throw new IllegalArgumentException ("locale is required" );
80
82
}
81
83
this .randomService = randomService ;
82
- locale = normalizeLocale (locale );
84
+ this .locale2localesChain = new HashMap <>();
85
+ setCurrentLocale (locale );
86
+ }
83
87
84
- localesChain = localeChain (locale );
85
- for (final Locale l : localesChain ) {
88
+ public void setCurrentLocale (Locale locale ) {
89
+ currentLocale = normalizeLocale (locale );
90
+ if (locale2localesChain .containsKey (currentLocale )) {
91
+ return ;
92
+ }
93
+ locale2localesChain .put (currentLocale , localeChain (currentLocale ));
94
+ for (final Locale l : locale2localesChain .get (currentLocale )) {
86
95
fakeValuesInterfaceMap .computeIfAbsent (l , this ::getCachedFakeValue );
87
96
}
88
97
}
89
98
90
99
private FakeValuesInterface getCachedFakeValue (Locale locale ) {
91
- if (Locale . ENGLISH .equals (locale )) {
100
+ if (DEFAULT_LOCALE .equals (locale )) {
92
101
return FakeValuesGrouping .getEnglishFakeValueGrouping ();
93
102
}
94
103
return FAKE_VALUES_CACHE .computeIfAbsent (locale , FakeValues ::new );
@@ -126,18 +135,18 @@ public void addPath(Locale locale, Path path) {
126
135
* @return a list of {@link Locale} instances
127
136
*/
128
137
protected List <Locale > localeChain (Locale from ) {
129
- if (Locale . ENGLISH .equals (from )) {
130
- return Collections .singletonList (Locale . ENGLISH );
138
+ if (DEFAULT_LOCALE .equals (from )) {
139
+ return Collections .singletonList (DEFAULT_LOCALE );
131
140
}
132
141
133
142
final Locale normalized = normalizeLocale (from );
134
143
135
144
final List <Locale > chain = new ArrayList <>(3 );
136
145
chain .add (normalized );
137
- if (!"" .equals (normalized .getCountry ()) && !Locale . ENGLISH .getLanguage ().equals (normalized .getLanguage ())) {
146
+ if (!"" .equals (normalized .getCountry ()) && !DEFAULT_LOCALE .getLanguage ().equals (normalized .getLanguage ())) {
138
147
chain .add (new Locale (normalized .getLanguage ()));
139
148
}
140
- chain .add (Locale . ENGLISH ); // default
149
+ chain .add (DEFAULT_LOCALE ); // default
141
150
return chain ;
142
151
}
143
152
@@ -157,7 +166,11 @@ private Locale normalizeLocale(Locale locale) {
157
166
}
158
167
159
168
public List <Locale > getLocalesChain () {
160
- return localesChain ;
169
+ return locale2localesChain .get (currentLocale );
170
+ }
171
+
172
+ public Locale getCurrentLocale () {
173
+ return currentLocale ;
161
174
}
162
175
163
176
/**
@@ -219,13 +232,23 @@ public String safeFetch(String key, String defaultIfNull) {
219
232
* dot. E.g. name.first_name
220
233
*/
221
234
public Object fetchObject (String key ) {
222
- Object result = key2fetchedObject .get (key );
235
+ Object result = null ;
236
+ for (Locale locale : locale2localesChain .get (currentLocale )) {
237
+ // exclude default locale from cache checks
238
+ if (locale .equals (DEFAULT_LOCALE ) && locale2localesChain .get (currentLocale ).size () > 1 ) {
239
+ continue ;
240
+ }
241
+ if (key2fetchedObject .get (locale ) != null && (result = key2fetchedObject .get (locale ).get (key )) != null ) {
242
+ break ;
243
+ }
244
+ }
223
245
if (result != null ) {
224
246
return result ;
225
247
}
226
248
227
249
String [] path = split (key );
228
- for (Locale locale : localesChain ) {
250
+ Locale local2Add = null ;
251
+ for (Locale locale : locale2localesChain .get (currentLocale )) {
229
252
Object currentValue = fakeValuesInterfaceMap .get (locale );
230
253
for (int p = 0 ; currentValue != null && p < path .length ; p ++) {
231
254
String currentPath = path [p ];
@@ -237,10 +260,14 @@ public Object fetchObject(String key) {
237
260
}
238
261
result = currentValue ;
239
262
if (result != null ) {
263
+ local2Add = locale ;
264
+ key2fetchedObject .putIfAbsent (local2Add , new HashMap <>());
240
265
break ;
241
266
}
242
267
}
243
- key2fetchedObject .put (key , result );
268
+ if (local2Add != null ) {
269
+ key2fetchedObject .get (local2Add ).put (key , result );
270
+ }
244
271
return result ;
245
272
}
246
273
@@ -417,11 +444,12 @@ public String resolve(String key, Object current, Faker root) {
417
444
* #{Person.hello_someone} will result in a method call to person.helloSomeone();
418
445
*/
419
446
public String resolve (String key , Object current , Faker root , Supplier <String > exceptionMessage ) {
420
- String expression = root == null ? key2Expression .get (key ) : null ;
447
+ String expression = root == null ? key2Expression .get (currentLocale ). get ( key ) : null ;
421
448
if (expression == null ) {
422
449
expression = safeFetch (key , null );
423
450
if (root == null ) {
424
- key2Expression .put (key , expression );
451
+ key2Expression .putIfAbsent (currentLocale , new HashMap <>());
452
+ key2Expression .get (currentLocale ).put (key , expression );
425
453
}
426
454
}
427
455
0 commit comments