1
1
package dev .openfeature .sdk ;
2
2
3
- import dev .openfeature .sdk .exceptions .*;
3
+ import java .util .ArrayList ;
4
+ import java .util .Arrays ;
5
+ import java .util .Collections ;
6
+ import java .util .HashMap ;
7
+ import java .util .Map ;
8
+ import java .util .List ;
9
+ import java .util .function .Consumer ;
10
+
11
+ import dev .openfeature .sdk .exceptions .ExceptionUtils ;
12
+ import dev .openfeature .sdk .exceptions .FatalError ;
13
+ import dev .openfeature .sdk .exceptions .GeneralError ;
14
+ import dev .openfeature .sdk .exceptions .OpenFeatureError ;
15
+ import dev .openfeature .sdk .exceptions .ProviderNotReadyError ;
4
16
import dev .openfeature .sdk .internal .AutoCloseableLock ;
5
17
import dev .openfeature .sdk .internal .AutoCloseableReentrantReadWriteLock ;
6
18
import dev .openfeature .sdk .internal .ObjectUtils ;
7
19
import lombok .Getter ;
8
20
import lombok .extern .slf4j .Slf4j ;
9
21
10
- import java .util .*;
11
- import java .util .function .Consumer ;
12
-
13
22
/**
14
23
* OpenFeature Client implementation.
15
24
* You should not instantiate this or reference this class.
19
28
* @deprecated // TODO: eventually we will make this non-public. See issue #872
20
29
*/
21
30
@ Slf4j
22
- @ SuppressWarnings ({"PMD.DataflowAnomalyAnalysis" , "PMD.BeanMembersShouldSerialize" , "PMD.UnusedLocalVariable" ,
23
- "unchecked" , "rawtypes" })
31
+ @ SuppressWarnings ({ "PMD.DataflowAnomalyAnalysis" , "PMD.BeanMembersShouldSerialize" , "PMD.UnusedLocalVariable" ,
32
+ "unchecked" , "rawtypes" })
24
33
@ Deprecated () // TODO: eventually we will make this non-public. See issue #872
25
34
public class OpenFeatureClient implements Client {
26
35
@@ -39,18 +48,18 @@ public class OpenFeatureClient implements Client {
39
48
* Deprecated public constructor. Use OpenFeature.API.getClient() instead.
40
49
*
41
50
* @param openFeatureAPI Backing global singleton
42
- * @param domain An identifier which logically binds clients with providers (used by observability tools).
51
+ * @param domain An identifier which logically binds clients with
52
+ * providers (used by observability tools).
43
53
* @param version Version of the client (used by observability tools).
44
54
* @deprecated Do not use this constructor. It's for internal use only.
45
- * Clients created using it will not run event handlers.
46
- * Use the OpenFeatureAPI's getClient factory method instead.
55
+ * Clients created using it will not run event handlers.
56
+ * Use the OpenFeatureAPI's getClient factory method instead.
47
57
*/
48
58
@ Deprecated () // TODO: eventually we will make this non-public. See issue #872
49
59
public OpenFeatureClient (
50
60
OpenFeatureAPI openFeatureAPI ,
51
61
String domain ,
52
- String version
53
- ) {
62
+ String version ) {
54
63
this .openfeatureApi = openFeatureAPI ;
55
64
this .domain = domain ;
56
65
this .version = version ;
@@ -106,7 +115,7 @@ public EvaluationContext getEvaluationContext() {
106
115
}
107
116
108
117
private <T > FlagEvaluationDetails <T > evaluateFlag (FlagValueType type , String key , T defaultValue ,
109
- EvaluationContext ctx , FlagEvaluationOptions options ) {
118
+ EvaluationContext ctx , FlagEvaluationOptions options ) {
110
119
FlagEvaluationOptions flagOptions = ObjectUtils .defaultIfNull (options ,
111
120
() -> FlagEvaluationOptions .builder ().build ());
112
121
Map <String , Object > hints = Collections .unmodifiableMap (flagOptions .getHookHints ());
@@ -182,29 +191,23 @@ private static <T> void enrichDetailsWithErrorDefaults(T defaultValue, FlagEvalu
182
191
* @return merged evaluation context
183
192
*/
184
193
private EvaluationContext mergeEvaluationContext (EvaluationContext invocationContext ) {
185
- // avoid any unnecessary context instantiations and stream usage here; this is call with every evaluation.
186
194
final EvaluationContext apiContext = openfeatureApi .getEvaluationContext ();
187
195
final EvaluationContext clientContext = this .getEvaluationContext ();
188
196
final EvaluationContext transactionContext = openfeatureApi .getTransactionContext ();
189
- final List <EvaluationContext > contextsToMerge = new ArrayList <>();
190
- if (apiContext != null ) {
191
- contextsToMerge .add (apiContext );
192
- }
193
- if (transactionContext != null ) {
194
- contextsToMerge .add (transactionContext );
195
- }
196
- if (clientContext != null ) {
197
- contextsToMerge .add (clientContext );
198
- }
199
- if (invocationContext != null ) {
200
- contextsToMerge .add (invocationContext );
201
- }
197
+ return mergeContextMaps (apiContext , transactionContext , clientContext , invocationContext );
198
+ }
202
199
203
- EvaluationContext merged = new ImmutableContext ();
204
- for (EvaluationContext evaluationContext : contextsToMerge ) {
205
- merged = merged .merge (evaluationContext );
200
+ private EvaluationContext mergeContextMaps (EvaluationContext ... contexts ) {
201
+ // avoid any unnecessary context instantiations and stream usage here; this is
202
+ // called with every evaluation.
203
+ Map merged = new HashMap <>();
204
+ for (EvaluationContext evaluationContext : contexts ) {
205
+ if (evaluationContext != null && !evaluationContext .isEmpty ()) {
206
+ merged = EvaluationContext .mergeMaps (ImmutableStructure ::new , merged ,
207
+ evaluationContext .asUnmodifiableMap ());
208
+ }
206
209
}
207
- return merged ;
210
+ return new ImmutableContext ( merged ) ;
208
211
}
209
212
210
213
private <T > ProviderEvaluation <?> createProviderEvaluation (
@@ -241,7 +244,7 @@ public Boolean getBooleanValue(String key, Boolean defaultValue, EvaluationConte
241
244
242
245
@ Override
243
246
public Boolean getBooleanValue (String key , Boolean defaultValue , EvaluationContext ctx ,
244
- FlagEvaluationOptions options ) {
247
+ FlagEvaluationOptions options ) {
245
248
return getBooleanDetails (key , defaultValue , ctx , options ).getValue ();
246
249
}
247
250
@@ -257,7 +260,7 @@ public FlagEvaluationDetails<Boolean> getBooleanDetails(String key, Boolean defa
257
260
258
261
@ Override
259
262
public FlagEvaluationDetails <Boolean > getBooleanDetails (String key , Boolean defaultValue , EvaluationContext ctx ,
260
- FlagEvaluationOptions options ) {
263
+ FlagEvaluationOptions options ) {
261
264
return this .evaluateFlag (FlagValueType .BOOLEAN , key , defaultValue , ctx , options );
262
265
}
263
266
@@ -273,7 +276,7 @@ public String getStringValue(String key, String defaultValue, EvaluationContext
273
276
274
277
@ Override
275
278
public String getStringValue (String key , String defaultValue , EvaluationContext ctx ,
276
- FlagEvaluationOptions options ) {
279
+ FlagEvaluationOptions options ) {
277
280
return getStringDetails (key , defaultValue , ctx , options ).getValue ();
278
281
}
279
282
@@ -289,7 +292,7 @@ public FlagEvaluationDetails<String> getStringDetails(String key, String default
289
292
290
293
@ Override
291
294
public FlagEvaluationDetails <String > getStringDetails (String key , String defaultValue , EvaluationContext ctx ,
292
- FlagEvaluationOptions options ) {
295
+ FlagEvaluationOptions options ) {
293
296
return this .evaluateFlag (FlagValueType .STRING , key , defaultValue , ctx , options );
294
297
}
295
298
@@ -305,7 +308,7 @@ public Integer getIntegerValue(String key, Integer defaultValue, EvaluationConte
305
308
306
309
@ Override
307
310
public Integer getIntegerValue (String key , Integer defaultValue , EvaluationContext ctx ,
308
- FlagEvaluationOptions options ) {
311
+ FlagEvaluationOptions options ) {
309
312
return getIntegerDetails (key , defaultValue , ctx , options ).getValue ();
310
313
}
311
314
@@ -321,7 +324,7 @@ public FlagEvaluationDetails<Integer> getIntegerDetails(String key, Integer defa
321
324
322
325
@ Override
323
326
public FlagEvaluationDetails <Integer > getIntegerDetails (String key , Integer defaultValue , EvaluationContext ctx ,
324
- FlagEvaluationOptions options ) {
327
+ FlagEvaluationOptions options ) {
325
328
return this .evaluateFlag (FlagValueType .INTEGER , key , defaultValue , ctx , options );
326
329
}
327
330
@@ -337,7 +340,7 @@ public Double getDoubleValue(String key, Double defaultValue, EvaluationContext
337
340
338
341
@ Override
339
342
public Double getDoubleValue (String key , Double defaultValue , EvaluationContext ctx ,
340
- FlagEvaluationOptions options ) {
343
+ FlagEvaluationOptions options ) {
341
344
return this .evaluateFlag (FlagValueType .DOUBLE , key , defaultValue , ctx , options ).getValue ();
342
345
}
343
346
@@ -353,7 +356,7 @@ public FlagEvaluationDetails<Double> getDoubleDetails(String key, Double default
353
356
354
357
@ Override
355
358
public FlagEvaluationDetails <Double > getDoubleDetails (String key , Double defaultValue , EvaluationContext ctx ,
356
- FlagEvaluationOptions options ) {
359
+ FlagEvaluationOptions options ) {
357
360
return this .evaluateFlag (FlagValueType .DOUBLE , key , defaultValue , ctx , options );
358
361
}
359
362
@@ -369,7 +372,7 @@ public Value getObjectValue(String key, Value defaultValue, EvaluationContext ct
369
372
370
373
@ Override
371
374
public Value getObjectValue (String key , Value defaultValue , EvaluationContext ctx ,
372
- FlagEvaluationOptions options ) {
375
+ FlagEvaluationOptions options ) {
373
376
return getObjectDetails (key , defaultValue , ctx , options ).getValue ();
374
377
}
375
378
@@ -380,13 +383,13 @@ public FlagEvaluationDetails<Value> getObjectDetails(String key, Value defaultVa
380
383
381
384
@ Override
382
385
public FlagEvaluationDetails <Value > getObjectDetails (String key , Value defaultValue ,
383
- EvaluationContext ctx ) {
386
+ EvaluationContext ctx ) {
384
387
return getObjectDetails (key , defaultValue , ctx , FlagEvaluationOptions .builder ().build ());
385
388
}
386
389
387
390
@ Override
388
391
public FlagEvaluationDetails <Value > getObjectDetails (String key , Value defaultValue , EvaluationContext ctx ,
389
- FlagEvaluationOptions options ) {
392
+ FlagEvaluationOptions options ) {
390
393
return this .evaluateFlag (FlagValueType .OBJECT , key , defaultValue , ctx , options );
391
394
}
392
395
0 commit comments