11package dev .openfeature .sdk ;
22
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 ;
416import dev .openfeature .sdk .internal .AutoCloseableLock ;
517import dev .openfeature .sdk .internal .AutoCloseableReentrantReadWriteLock ;
618import dev .openfeature .sdk .internal .ObjectUtils ;
719import lombok .Getter ;
820import lombok .extern .slf4j .Slf4j ;
921
10- import java .util .*;
11- import java .util .function .Consumer ;
12-
1322/**
1423 * OpenFeature Client implementation.
1524 * You should not instantiate this or reference this class.
1928 * @deprecated // TODO: eventually we will make this non-public. See issue #872
2029 */
2130@ Slf4j
22- @ SuppressWarnings ({"PMD.DataflowAnomalyAnalysis" , "PMD.BeanMembersShouldSerialize" , "PMD.UnusedLocalVariable" ,
23- "unchecked" , "rawtypes" })
31+ @ SuppressWarnings ({ "PMD.DataflowAnomalyAnalysis" , "PMD.BeanMembersShouldSerialize" , "PMD.UnusedLocalVariable" ,
32+ "unchecked" , "rawtypes" })
2433@ Deprecated () // TODO: eventually we will make this non-public. See issue #872
2534public class OpenFeatureClient implements Client {
2635
@@ -39,18 +48,18 @@ public class OpenFeatureClient implements Client {
3948 * Deprecated public constructor. Use OpenFeature.API.getClient() instead.
4049 *
4150 * @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).
4353 * @param version Version of the client (used by observability tools).
4454 * @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.
4757 */
4858 @ Deprecated () // TODO: eventually we will make this non-public. See issue #872
4959 public OpenFeatureClient (
5060 OpenFeatureAPI openFeatureAPI ,
5161 String domain ,
52- String version
53- ) {
62+ String version ) {
5463 this .openfeatureApi = openFeatureAPI ;
5564 this .domain = domain ;
5665 this .version = version ;
@@ -106,7 +115,7 @@ public EvaluationContext getEvaluationContext() {
106115 }
107116
108117 private <T > FlagEvaluationDetails <T > evaluateFlag (FlagValueType type , String key , T defaultValue ,
109- EvaluationContext ctx , FlagEvaluationOptions options ) {
118+ EvaluationContext ctx , FlagEvaluationOptions options ) {
110119 FlagEvaluationOptions flagOptions = ObjectUtils .defaultIfNull (options ,
111120 () -> FlagEvaluationOptions .builder ().build ());
112121 Map <String , Object > hints = Collections .unmodifiableMap (flagOptions .getHookHints ());
@@ -182,29 +191,23 @@ private static <T> void enrichDetailsWithErrorDefaults(T defaultValue, FlagEvalu
182191 * @return merged evaluation context
183192 */
184193 private EvaluationContext mergeEvaluationContext (EvaluationContext invocationContext ) {
185- // avoid any unnecessary context instantiations and stream usage here; this is call with every evaluation.
186194 final EvaluationContext apiContext = openfeatureApi .getEvaluationContext ();
187195 final EvaluationContext clientContext = this .getEvaluationContext ();
188196 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+ }
202199
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+ }
206209 }
207- return merged ;
210+ return new ImmutableContext ( merged ) ;
208211 }
209212
210213 private <T > ProviderEvaluation <?> createProviderEvaluation (
@@ -241,7 +244,7 @@ public Boolean getBooleanValue(String key, Boolean defaultValue, EvaluationConte
241244
242245 @ Override
243246 public Boolean getBooleanValue (String key , Boolean defaultValue , EvaluationContext ctx ,
244- FlagEvaluationOptions options ) {
247+ FlagEvaluationOptions options ) {
245248 return getBooleanDetails (key , defaultValue , ctx , options ).getValue ();
246249 }
247250
@@ -257,7 +260,7 @@ public FlagEvaluationDetails<Boolean> getBooleanDetails(String key, Boolean defa
257260
258261 @ Override
259262 public FlagEvaluationDetails <Boolean > getBooleanDetails (String key , Boolean defaultValue , EvaluationContext ctx ,
260- FlagEvaluationOptions options ) {
263+ FlagEvaluationOptions options ) {
261264 return this .evaluateFlag (FlagValueType .BOOLEAN , key , defaultValue , ctx , options );
262265 }
263266
@@ -273,7 +276,7 @@ public String getStringValue(String key, String defaultValue, EvaluationContext
273276
274277 @ Override
275278 public String getStringValue (String key , String defaultValue , EvaluationContext ctx ,
276- FlagEvaluationOptions options ) {
279+ FlagEvaluationOptions options ) {
277280 return getStringDetails (key , defaultValue , ctx , options ).getValue ();
278281 }
279282
@@ -289,7 +292,7 @@ public FlagEvaluationDetails<String> getStringDetails(String key, String default
289292
290293 @ Override
291294 public FlagEvaluationDetails <String > getStringDetails (String key , String defaultValue , EvaluationContext ctx ,
292- FlagEvaluationOptions options ) {
295+ FlagEvaluationOptions options ) {
293296 return this .evaluateFlag (FlagValueType .STRING , key , defaultValue , ctx , options );
294297 }
295298
@@ -305,7 +308,7 @@ public Integer getIntegerValue(String key, Integer defaultValue, EvaluationConte
305308
306309 @ Override
307310 public Integer getIntegerValue (String key , Integer defaultValue , EvaluationContext ctx ,
308- FlagEvaluationOptions options ) {
311+ FlagEvaluationOptions options ) {
309312 return getIntegerDetails (key , defaultValue , ctx , options ).getValue ();
310313 }
311314
@@ -321,7 +324,7 @@ public FlagEvaluationDetails<Integer> getIntegerDetails(String key, Integer defa
321324
322325 @ Override
323326 public FlagEvaluationDetails <Integer > getIntegerDetails (String key , Integer defaultValue , EvaluationContext ctx ,
324- FlagEvaluationOptions options ) {
327+ FlagEvaluationOptions options ) {
325328 return this .evaluateFlag (FlagValueType .INTEGER , key , defaultValue , ctx , options );
326329 }
327330
@@ -337,7 +340,7 @@ public Double getDoubleValue(String key, Double defaultValue, EvaluationContext
337340
338341 @ Override
339342 public Double getDoubleValue (String key , Double defaultValue , EvaluationContext ctx ,
340- FlagEvaluationOptions options ) {
343+ FlagEvaluationOptions options ) {
341344 return this .evaluateFlag (FlagValueType .DOUBLE , key , defaultValue , ctx , options ).getValue ();
342345 }
343346
@@ -353,7 +356,7 @@ public FlagEvaluationDetails<Double> getDoubleDetails(String key, Double default
353356
354357 @ Override
355358 public FlagEvaluationDetails <Double > getDoubleDetails (String key , Double defaultValue , EvaluationContext ctx ,
356- FlagEvaluationOptions options ) {
359+ FlagEvaluationOptions options ) {
357360 return this .evaluateFlag (FlagValueType .DOUBLE , key , defaultValue , ctx , options );
358361 }
359362
@@ -369,7 +372,7 @@ public Value getObjectValue(String key, Value defaultValue, EvaluationContext ct
369372
370373 @ Override
371374 public Value getObjectValue (String key , Value defaultValue , EvaluationContext ctx ,
372- FlagEvaluationOptions options ) {
375+ FlagEvaluationOptions options ) {
373376 return getObjectDetails (key , defaultValue , ctx , options ).getValue ();
374377 }
375378
@@ -380,13 +383,13 @@ public FlagEvaluationDetails<Value> getObjectDetails(String key, Value defaultVa
380383
381384 @ Override
382385 public FlagEvaluationDetails <Value > getObjectDetails (String key , Value defaultValue ,
383- EvaluationContext ctx ) {
386+ EvaluationContext ctx ) {
384387 return getObjectDetails (key , defaultValue , ctx , FlagEvaluationOptions .builder ().build ());
385388 }
386389
387390 @ Override
388391 public FlagEvaluationDetails <Value > getObjectDetails (String key , Value defaultValue , EvaluationContext ctx ,
389- FlagEvaluationOptions options ) {
392+ FlagEvaluationOptions options ) {
390393 return this .evaluateFlag (FlagValueType .OBJECT , key , defaultValue , ctx , options );
391394 }
392395
0 commit comments