Skip to content

Commit 205c480

Browse files
committed
Merging yasir/multi-user-context.
2 parents 684e626 + fa98fa4 commit 205c480

File tree

12 files changed

+220
-22
lines changed

12 files changed

+220
-22
lines changed

android/src/main/java/com/optimizely/optimizely_flutter_sdk/OptimizelyFlutterClient.java

Lines changed: 49 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,14 @@
4848
import com.optimizely.ab.optimizelydecision.OptimizelyDecideOption;
4949
import com.optimizely.ab.optimizelydecision.OptimizelyDecision;
5050
import com.optimizely.optimizely_flutter_sdk.helper_classes.ArgumentsParser;
51+
import com.optimizely.optimizely_flutter_sdk.helper_classes.Utils;
5152

5253
import static com.optimizely.optimizely_flutter_sdk.helper_classes.Constants.*;
5354

5455
import java.util.Collections;
5556
import java.util.LinkedHashMap;
5657
import java.util.List;
58+
import java.util.Objects;
5759
import java.util.concurrent.ArrayBlockingQueue;
5860
import java.util.concurrent.TimeUnit;
5961

@@ -62,7 +64,7 @@ public class OptimizelyFlutterClient {
6264
protected Activity activity;
6365

6466
protected static final Map<String, OptimizelyManager> optimizelyManagerTracker = new HashMap<>();
65-
protected static final Map<String, OptimizelyUserContext> userContextsTracker = new HashMap<>();
67+
protected static final Map<String, Map<String, OptimizelyUserContext>> userContextsTracker = new HashMap<>();
6668
protected static final Map<Integer, Integer> notificationIdsTracker = new HashMap<>();
6769

6870

@@ -161,18 +163,21 @@ protected void createUserContext(ArgumentsParser argumentsParser, @NonNull Resul
161163
return;
162164
}
163165
try {
164-
OptimizelyUserContext optlyUserContext = null;
165-
if (attributes != null) {
166-
optlyUserContext = optimizelyClient.createUserContext(userId, attributes);
167-
userContextsTracker.put(sdkKey, optlyUserContext);
166+
String userContextId = Utils.getRandomUUID();
167+
168+
OptimizelyUserContext optlyUserContext = optimizelyClient.createUserContext(userId, attributes);
169+
if (optlyUserContext != null) {
170+
if (userContextsTracker.containsKey(sdkKey)) {
171+
userContextsTracker.get(sdkKey).put(userContextId, optlyUserContext);
172+
} else {
173+
userContextsTracker.put(sdkKey, Collections.singletonMap(userContextId, optlyUserContext));
174+
}
175+
result.success(createResponse(true,
176+
Collections.singletonMap(RequestParameterKey.USER_CONTEXT_ID, optlyUserContext),
177+
SuccessMessage.USER_CONTEXT_CREATED));
168178
} else {
169-
optlyUserContext = optimizelyClient.createUserContext(userId);
170-
userContextsTracker.put(sdkKey, optlyUserContext);
171-
}
172-
if (optlyUserContext != null)
173-
result.success(createResponse(true, SuccessMessage.USER_CONTEXT_CREATED));
174-
else
175179
result.success(createResponse(false, "User context not created "));
180+
}
176181
} catch (Exception ex) {
177182
result.success(createResponse(false, ex.getMessage()));
178183
}
@@ -185,7 +190,7 @@ protected void decide(ArgumentsParser argumentsParser, @NonNull Result result) {
185190
return;
186191
}
187192

188-
OptimizelyUserContext userContext = getUserContext(sdkKey);
193+
OptimizelyUserContext userContext = getUserContext(argumentsParser);
189194
if (userContext == null) {
190195
result.success(createResponse(false, ErrorMessage.USER_CONTEXT_NOT_FOUND));
191196
return;
@@ -219,7 +224,7 @@ protected void setForcedDecision(ArgumentsParser argumentsParser, @NonNull Resul
219224
result.success(createResponse(false, ErrorMessage.INVALID_PARAMS));
220225
return;
221226
}
222-
OptimizelyUserContext userContext = getUserContext(sdkKey);
227+
OptimizelyUserContext userContext = getUserContext(argumentsParser);
223228
if (userContext == null) {
224229
result.success(createResponse(false, ErrorMessage.USER_CONTEXT_NOT_FOUND));
225230
return;
@@ -249,7 +254,7 @@ protected void getForcedDecision(ArgumentsParser argumentsParser, @NonNull Resul
249254
result.success(createResponse(false, ErrorMessage.INVALID_PARAMS));
250255
return;
251256
}
252-
OptimizelyUserContext userContext = getUserContext(sdkKey);
257+
OptimizelyUserContext userContext = getUserContext(argumentsParser);
253258
if (userContext == null) {
254259
result.success(createResponse(false, ErrorMessage.USER_CONTEXT_NOT_FOUND));
255260
return;
@@ -276,7 +281,7 @@ protected void removeForcedDecision(ArgumentsParser argumentsParser, @NonNull Re
276281
result.success(createResponse(false, ErrorMessage.INVALID_PARAMS));
277282
return;
278283
}
279-
OptimizelyUserContext userContext = getUserContext(sdkKey);
284+
OptimizelyUserContext userContext = getUserContext(argumentsParser);
280285
if (userContext == null) {
281286
result.success(createResponse(false, ErrorMessage.USER_CONTEXT_NOT_FOUND));
282287
return;
@@ -304,7 +309,7 @@ protected void removeAllForcedDecisions(ArgumentsParser argumentsParser, @NonNul
304309
result.success(createResponse(false, ErrorMessage.INVALID_PARAMS));
305310
return;
306311
}
307-
OptimizelyUserContext userContext = getUserContext(sdkKey);
312+
OptimizelyUserContext userContext = getUserContext(argumentsParser);
308313
if (userContext == null) {
309314
result.success(createResponse(false, ErrorMessage.USER_CONTEXT_NOT_FOUND));
310315
return;
@@ -342,7 +347,7 @@ protected void trackEvent(ArgumentsParser argumentsParser, @NonNull Result resul
342347
result.success(createResponse(false, ErrorMessage.INVALID_PARAMS));
343348
return;
344349
}
345-
OptimizelyUserContext userContext = getUserContext(sdkKey);
350+
OptimizelyUserContext userContext = getUserContext(argumentsParser);
346351

347352
String eventKey = argumentsParser.getEventKey();
348353
Map<String, Object> eventTags = argumentsParser.getEventTags();
@@ -366,13 +371,31 @@ protected void trackEvent(ArgumentsParser argumentsParser, @NonNull Result resul
366371
}
367372
}
368373

374+
protected void getUserId(ArgumentsParser argumentsParser, @NonNull Result result) {
375+
OptimizelyUserContext userContext = getUserContext(argumentsParser);
376+
if (userContext == null) {
377+
result.success(createResponse(false, ErrorMessage.USER_CONTEXT_NOT_FOUND));
378+
return;
379+
}
380+
result.success(createResponse(true, Collections.singletonMap(RequestParameterKey.USER_ID, userContext.getUserId()), ""));
381+
}
382+
383+
protected void getAttributes(ArgumentsParser argumentsParser, @NonNull Result result) {
384+
OptimizelyUserContext userContext = getUserContext(argumentsParser);
385+
if (userContext == null) {
386+
result.success(createResponse(false, ErrorMessage.USER_CONTEXT_NOT_FOUND));
387+
return;
388+
}
389+
result.success(createResponse(true, Collections.singletonMap(RequestParameterKey.ATTRIBUTES, userContext.getAttributes()), ""));
390+
}
391+
369392
protected void setAttribute(ArgumentsParser argumentsParser, @NonNull Result result) {
370393
String sdkKey = argumentsParser.getSdkKey();
371394
if (sdkKey == null) {
372395
result.success(createResponse(false, ErrorMessage.INVALID_PARAMS));
373396
return;
374397
}
375-
OptimizelyUserContext userContext = getUserContext(sdkKey);
398+
OptimizelyUserContext userContext = getUserContext(argumentsParser);
376399

377400
Map<String, Object> attributes = argumentsParser.getAttributes();
378401
if (userContext == null) {
@@ -386,7 +409,7 @@ protected void setAttribute(ArgumentsParser argumentsParser, @NonNull Result res
386409
for (String attributeKey : attributes.keySet()) {
387410
userContext.setAttribute(attributeKey, attributes.get(attributeKey));
388411
}
389-
userContextsTracker.put(sdkKey, userContext);
412+
userContextsTracker.get(sdkKey).put(argumentsParser.getUserContextId(), userContext);
390413
result.success(createResponse(true, userContext.getAttributes(), SuccessMessage.ATTRIBUTES_ADDED));
391414
}
392415

@@ -455,8 +478,13 @@ public OptimizelyClient getOptimizelyClient(String SDKKey) {
455478
return optimizelyManagerTracker.get(SDKKey) == null? null : optimizelyManagerTracker.get(SDKKey).getOptimizely();
456479
}
457480

458-
public OptimizelyUserContext getUserContext(String SDKKey) {
459-
return userContextsTracker.get(SDKKey);
481+
public OptimizelyUserContext getUserContext(ArgumentsParser argumentsParser) {
482+
String SDKKey = argumentsParser.getSdkKey();
483+
String userContextId = argumentsParser.getUserContextId();
484+
if (userContextId == null || !userContextsTracker.get(SDKKey).containsKey(userContextId)) {
485+
return null;
486+
}
487+
return userContextsTracker.get(SDKKey).get(userContextId);
460488
}
461489

462490
protected void addNotificationListener(ArgumentsParser argumentsParser, @NonNull Result result) {

android/src/main/java/com/optimizely/optimizely_flutter_sdk/OptimizelyFlutterSdkPlugin.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,14 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
6262
createUserContext(argumentsParser, result);
6363
break;
6464
}
65+
case APIs.GET_USER_ID: {
66+
getUserId(argumentsParser, result);
67+
break;
68+
}
69+
case APIs.GET_ATTRIBUTES: {
70+
getAttributes(argumentsParser, result);
71+
break;
72+
}
6573
case APIs.SET_ATTRIBUTES: {
6674
setAttribute(argumentsParser, result);
6775
break;

android/src/main/java/com/optimizely/optimizely_flutter_sdk/helper_classes/ArgumentsParser.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ public String getUserID() {
4343
return (String) arguments.get(Constants.RequestParameterKey.USER_ID);
4444
}
4545

46+
public String getUserContextId() {
47+
return (String) arguments.get(Constants.RequestParameterKey.USER_CONTEXT_ID);
48+
}
49+
4650
public Map<String, Object> getAttributes() {
4751
return (Map<String, Object>) arguments.get(Constants.RequestParameterKey.ATTRIBUTES);
4852
}

android/src/main/java/com/optimizely/optimizely_flutter_sdk/helper_classes/Constants.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ public static class APIs {
2121
public static final String INITIALIZE = "initialize";
2222
public static final String GET_OPTIMIZELY_CONFIG = "getOptimizelyConfig";
2323
public static final String CREATE_USER_CONTEXT = "createUserContext";
24+
public static final String GET_USER_ID = "getUserId";
25+
public static final String GET_ATTRIBUTES = "getAttributes";
2426
public static final String SET_ATTRIBUTES="setAttributes";
2527
public static final String GET_FORCED_DECISION = "getForcedDecision";
2628
public static final String REMOVE_FORCED_DECISION = "removeForcedDecision";
@@ -42,6 +44,7 @@ public static class NotificationType {
4244
public static class RequestParameterKey {
4345
public static final String SDK_KEY = "sdkKey";
4446
public static final String USER_ID = "userID";
47+
public static final String USER_CONTEXT_ID = "userContextId";
4548
public static final String NOTIFICATION_ID = "id";
4649
public static final String NOTIFICATION_TYPE = "type";
4750
public static final String NOTIFICATION_PAYLOAD = "payload";

android/src/main/java/com/optimizely/optimizely_flutter_sdk/helper_classes/Utils.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,19 @@
1919
import java.util.HashMap;
2020
import java.util.List;
2121
import java.util.Map;
22+
import java.util.UUID;
23+
2224
import static com.optimizely.ab.notification.DecisionNotification.FeatureVariableDecisionNotificationBuilder.SOURCE_INFO;
2325

2426
import com.google.common.base.CaseFormat;
2527
import com.optimizely.ab.optimizelydecision.OptimizelyDecideOption;
2628

2729
public class Utils {
2830

31+
public static String getRandomUUID() {
32+
return UUID.randomUUID().toString();
33+
}
34+
2935
public static List<OptimizelyDecideOption> getDecideOptions(List<String> options) {
3036
if(options == null || options.isEmpty()) {
3137
return null;

ios/Classes/HelperClasses/Constants.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ struct API {
2222
static let activate = "activate"
2323
static let getVariation = "getVariation"
2424
static let createUserContext = "createUserContext"
25+
static let getUserId = "getUserId"
26+
static let getAttributes = "getAttributes"
2527
static let setAttributes = "setAttributes"
2628
static let trackEvent = "trackEvent"
2729
static let decide = "decide"

ios/Classes/SwiftOptimizelyFlutterSdkPlugin.swift

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ public class SwiftOptimizelyFlutterSdkPlugin: NSObject, FlutterPlugin {
5454
case API.activate: activate(call, result: result)
5555
case API.getVariation: getVariation(call, result: result)
5656
case API.createUserContext: createUserContext(call, result: result)
57+
case API.getUserId: getUserId(call, result: result)
58+
case API.getAttributes: getAttributes(call, result: result)
5759
case API.setAttributes: setAttributes(call, result: result)
5860
case API.trackEvent: trackEvent(call, result: result)
5961
case API.decide: decide(call, result: result)
@@ -256,7 +258,25 @@ public class SwiftOptimizelyFlutterSdkPlugin: NSObject, FlutterPlugin {
256258
} else {
257259
userContextsTracker[sdkKey] = [userContextId: userContext]
258260
}
259-
result(self.createResponse(success: true,result: [RequestParameterKey.userContextId: userContextId], reason: SuccessMessage.userContextCreated))
261+
result(self.createResponse(success: true, result: [RequestParameterKey.userContextId: userContextId], reason: SuccessMessage.userContextCreated))
262+
}
263+
264+
/// Returns userId for the user context.
265+
func getUserId(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
266+
guard let usrContext = getUserContext(arguments: call.arguments) else {
267+
result(self.createResponse(success: false, reason: ErrorMessage.userContextNotFound))
268+
return
269+
}
270+
result(createResponse(success: true, result: [RequestParameterKey.userId: usrContext.userId]))
271+
}
272+
273+
/// Returns attributes for the user context.
274+
func getAttributes(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
275+
guard let usrContext = getUserContext(arguments: call.arguments) else {
276+
result(self.createResponse(success: false, reason: ErrorMessage.userContextNotFound))
277+
return
278+
}
279+
result(createResponse(success: true, result: [RequestParameterKey.attributes: usrContext.attributes]))
260280
}
261281

262282
/// Sets attributes for the user context.
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/// **************************************************************************
2+
/// Copyright 2022, Optimizely, Inc. and contributors *
3+
/// *
4+
/// Licensed under the Apache License, Version 2.0 (the "License"); *
5+
/// you may not use this file except in compliance with the License. *
6+
/// You may obtain a copy of the License at *
7+
/// *
8+
/// http://www.apache.org/licenses/LICENSE-2.0 *
9+
/// *
10+
/// Unless required by applicable law or agreed to in writing, software *
11+
/// distributed under the License is distributed on an "AS IS" BASIS, *
12+
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
13+
/// See the License for the specific language governing permissions and *
14+
/// limitations under the License. *
15+
///**************************************************************************/
16+
17+
import 'package:optimizely_flutter_sdk/src/data_objects/base_response.dart';
18+
import 'package:optimizely_flutter_sdk/src/utils/constants.dart';
19+
20+
class GetAttributesResponse extends BaseResponse {
21+
Map<String, dynamic> attributes = {};
22+
23+
GetAttributesResponse(Map<String, dynamic> json) : super(json) {
24+
if (json[Constants.responseResult] is Map<dynamic, dynamic>) {
25+
var response = Map<String, dynamic>.from(json[Constants.responseResult]);
26+
if (response[Constants.attributes] is Map<dynamic, dynamic>) {
27+
attributes = Map<String, dynamic>.from(response[Constants.attributes]);
28+
}
29+
}
30+
}
31+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/// **************************************************************************
2+
/// Copyright 2022, Optimizely, Inc. and contributors *
3+
/// *
4+
/// Licensed under the Apache License, Version 2.0 (the "License"); *
5+
/// you may not use this file except in compliance with the License. *
6+
/// You may obtain a copy of the License at *
7+
/// *
8+
/// http://www.apache.org/licenses/LICENSE-2.0 *
9+
/// *
10+
/// Unless required by applicable law or agreed to in writing, software *
11+
/// distributed under the License is distributed on an "AS IS" BASIS, *
12+
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
13+
/// See the License for the specific language governing permissions and *
14+
/// limitations under the License. *
15+
///**************************************************************************/
16+
17+
import 'package:optimizely_flutter_sdk/src/data_objects/base_response.dart';
18+
import 'package:optimizely_flutter_sdk/src/utils/constants.dart';
19+
20+
class GetUserIdResponse extends BaseResponse {
21+
String userId = "";
22+
23+
GetUserIdResponse(Map<String, dynamic> json) : super(json) {
24+
if (json[Constants.responseResult] is Map<dynamic, dynamic>) {
25+
var response = Map<String, dynamic>.from(json[Constants.responseResult]);
26+
if (response[Constants.userID] is String) {
27+
userId = response[Constants.userID];
28+
}
29+
}
30+
}
31+
}

lib/src/user_context/optimizely_user_context.dart

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ import 'package:flutter/services.dart';
1818
import 'package:optimizely_flutter_sdk/optimizely_flutter_sdk.dart';
1919
import 'package:optimizely_flutter_sdk/src/data_objects/base_response.dart';
2020
import 'package:optimizely_flutter_sdk/src/data_objects/decide_response.dart';
21+
import 'package:optimizely_flutter_sdk/src/data_objects/get_attributes_response.dart';
2122
import 'package:optimizely_flutter_sdk/src/data_objects/get_forced_decision_response.dart';
23+
import 'package:optimizely_flutter_sdk/src/data_objects/get_user_id_response.dart';
2224
import 'package:optimizely_flutter_sdk/src/utils/constants.dart';
2325
import 'package:optimizely_flutter_sdk/src/utils/utils.dart';
2426

@@ -50,6 +52,26 @@ class OptimizelyUserContext {
5052

5153
OptimizelyUserContext(this._sdkKey, this._userContextId, this._channel);
5254

55+
/// Returns userId for the user context.
56+
Future<GetUserIdResponse> getUserId() async {
57+
final result = Map<String, dynamic>.from(
58+
await _channel.invokeMethod(Constants.getUserIdMethod, {
59+
Constants.sdkKey: _sdkKey,
60+
Constants.userContextId: _userContextId,
61+
}));
62+
return GetUserIdResponse(result);
63+
}
64+
65+
/// Returns attributes for the user context.
66+
Future<GetAttributesResponse> getAttributes() async {
67+
final result = Map<String, dynamic>.from(
68+
await _channel.invokeMethod(Constants.getAttributesMethod, {
69+
Constants.sdkKey: _sdkKey,
70+
Constants.userContextId: _userContextId,
71+
}));
72+
return GetAttributesResponse(result);
73+
}
74+
5375
/// Sets attributes for the user context.
5476
Future<BaseResponse> setAttributes(Map<String, dynamic> attributes) async {
5577
final result = Map<String, dynamic>.from(

0 commit comments

Comments
 (0)