30
30
import org .slf4j .Logger ;
31
31
32
32
import java .util .Collections ;
33
+ import java .util .HashMap ;
33
34
import java .util .Map ;
34
35
35
36
/**
@@ -46,10 +47,51 @@ public class OptimizelyClient {
46
47
private final Logger logger ;
47
48
48
49
@ Nullable private Optimizely optimizely ;
50
+ @ Nullable private Map <String , String > defaultAttributes ;
49
51
50
52
OptimizelyClient (@ Nullable Optimizely optimizely , @ NonNull Logger logger ) {
51
53
this .optimizely = optimizely ;
52
54
this .logger = logger ;
55
+ /*
56
+ OptimizelyManager is initialized with an OptimizelyClient with a null optimizely property:
57
+ https://github.com/optimizely/android-sdk/blob/master/android-sdk/src/main/java/com/optimizely/ab/android/sdk/OptimizelyManager.java#L63
58
+ optimizely will remain null until OptimizelyManager#initialize has been called, so isValid checks for that. Otherwise apps would crash if
59
+ the public methods here were called before initialize.
60
+ So, we start with an empty map of default attributes until the manager is initialized.
61
+ */
62
+ defaultAttributes = Collections .EMPTY_MAP ;
63
+ }
64
+
65
+ /**
66
+ * Set default attributes to a non null attribute map.
67
+ * This is set by the Optimizely manager and includes things like os version and sdk version.
68
+ * @param attrs a map of default attributes.
69
+ */
70
+ protected void setDefaultAttributes (@ NonNull Map <String , String > attrs ) {
71
+ this .defaultAttributes = attrs ;
72
+ }
73
+
74
+ /**
75
+ * Return the default attributes map
76
+ * @return the map of default attributes
77
+ */
78
+ public @ NonNull Map <String , String > getDefaultAttributes () {
79
+ return this .defaultAttributes ;
80
+ }
81
+
82
+ /**
83
+ * Get the default attributes and combine them with the attributes passed in.
84
+ * The attributes passed in take precedence over the default attributes. So, you can override default attributes.
85
+ * @param attrs attributes that will be combined with default attributes.
86
+ * @return a new map of both the default attributes and attributes passed in.
87
+ */
88
+ private Map <String , String > getAllAttributes (@ NonNull Map <String , String > attrs ) {
89
+ Map <String ,String > combinedMap = new HashMap <String ,String >(defaultAttributes );
90
+
91
+ // this essentially overrides defaultAttributes if the attrs passed in have the same key.
92
+ combinedMap .putAll (attrs );
93
+
94
+ return combinedMap ;
53
95
}
54
96
55
97
/**
@@ -83,7 +125,7 @@ public class OptimizelyClient {
83
125
@ NonNull String userId ,
84
126
@ NonNull Map <String , String > attributes ) {
85
127
if (isValid ()) {
86
- return optimizely .activate (experimentKey , userId , attributes );
128
+ return optimizely .activate (experimentKey , userId , getAllAttributes ( attributes ) );
87
129
} else {
88
130
logger .warn ("Optimizely is not initialized, could not activate experiment {} for user {} " +
89
131
"with attributes" , experimentKey , userId );
@@ -140,7 +182,7 @@ public void track(@NonNull String eventName,
140
182
@ NonNull String userId ,
141
183
@ NonNull Map <String , String > attributes ) throws UnknownEventTypeException {
142
184
if (isValid ()) {
143
- optimizely .track (eventName , userId , attributes );
185
+ optimizely .track (eventName , userId , getAllAttributes ( attributes ) );
144
186
145
187
} else {
146
188
logger .warn ("Optimizely is not initialized, could not track event {} for user {} with attributes" ,
@@ -160,7 +202,7 @@ public void track(@NonNull String eventName,
160
202
@ NonNull Map <String , String > attributes ,
161
203
@ NonNull Map <String , ?> eventTags ) throws UnknownEventTypeException {
162
204
if (isValid ()) {
163
- optimizely .track (eventName , userId , attributes , eventTags );
205
+ optimizely .track (eventName , userId , getAllAttributes ( attributes ) , eventTags );
164
206
165
207
} else {
166
208
logger .warn ("Optimizely is not initialized, could not track event {} for user {}" +
@@ -200,7 +242,7 @@ public void track(@NonNull String eventName,
200
242
@ NonNull Map <String , String > attributes ,
201
243
long eventValue ) {
202
244
if (isValid ()) {
203
- optimizely .track (eventName , userId , attributes , eventValue );
245
+ optimizely .track (eventName , userId , getAllAttributes ( attributes ) , eventValue );
204
246
} else {
205
247
logger .warn ("Optimizely is not initialized, could not track event {} for user {}" +
206
248
" with value {} and attributes" , eventName , userId , eventValue );
@@ -234,7 +276,7 @@ public void track(@NonNull String eventName,
234
276
@ NonNull Map <String , String > attributes ,
235
277
boolean activateExperiment ) {
236
278
if (isValid ()) {
237
- return optimizely .getVariableString (variableKey , userId , attributes ,
279
+ return optimizely .getVariableString (variableKey , userId , getAllAttributes ( attributes ) ,
238
280
activateExperiment );
239
281
} else {
240
282
logger .warn ("Optimizely is not initialized, could not get live variable {} " +
@@ -383,7 +425,7 @@ public void track(@NonNull String eventName,
383
425
@ NonNull String userId ,
384
426
@ NonNull Map <String , String > attributes ) {
385
427
if (isValid ()) {
386
- return optimizely .getVariation (experimentKey , userId , attributes );
428
+ return optimizely .getVariation (experimentKey , userId , getAllAttributes ( attributes ) );
387
429
} else {
388
430
logger .warn ("Optimizely is not initialized, could not get variation for experiment {} " +
389
431
"for user {} with attributes" , experimentKey , userId );
0 commit comments