Skip to content

Commit ab02b49

Browse files
fix: long integer issue (#556)
1 parent 8bc0136 commit ab02b49

File tree

3 files changed

+275
-129
lines changed

3 files changed

+275
-129
lines changed

core-api/src/main/java/com/optimizely/ab/Optimizely.java

+129-41
Original file line numberDiff line numberDiff line change
@@ -20,44 +20,80 @@
2020
import com.optimizely.ab.bucketing.DecisionService;
2121
import com.optimizely.ab.bucketing.FeatureDecision;
2222
import com.optimizely.ab.bucketing.UserProfileService;
23-
import com.optimizely.ab.config.*;
23+
import com.optimizely.ab.config.AtomicProjectConfigManager;
24+
import com.optimizely.ab.config.DatafileProjectConfig;
25+
import com.optimizely.ab.config.EventType;
26+
import com.optimizely.ab.config.Experiment;
27+
import com.optimizely.ab.config.FeatureFlag;
28+
import com.optimizely.ab.config.FeatureVariable;
29+
import com.optimizely.ab.config.FeatureVariableUsageInstance;
30+
import com.optimizely.ab.config.ProjectConfig;
31+
import com.optimizely.ab.config.ProjectConfigManager;
32+
import com.optimizely.ab.config.Variation;
2433
import com.optimizely.ab.config.parser.ConfigParseException;
2534
import com.optimizely.ab.error.ErrorHandler;
2635
import com.optimizely.ab.error.NoOpErrorHandler;
27-
import com.optimizely.ab.event.*;
28-
import com.optimizely.ab.event.internal.*;
36+
import com.optimizely.ab.event.EventHandler;
37+
import com.optimizely.ab.event.EventProcessor;
38+
import com.optimizely.ab.event.ForwardingEventProcessor;
39+
import com.optimizely.ab.event.LogEvent;
40+
import com.optimizely.ab.event.NoopEventHandler;
41+
import com.optimizely.ab.event.internal.BuildVersionInfo;
42+
import com.optimizely.ab.event.internal.ClientEngineInfo;
43+
import com.optimizely.ab.event.internal.EventFactory;
44+
import com.optimizely.ab.event.internal.UserEvent;
45+
import com.optimizely.ab.event.internal.UserEventFactory;
2946
import com.optimizely.ab.event.internal.payload.EventBatch;
3047
import com.optimizely.ab.internal.NotificationRegistry;
31-
import com.optimizely.ab.notification.*;
32-
import com.optimizely.ab.odp.*;
48+
import com.optimizely.ab.notification.ActivateNotification;
49+
import com.optimizely.ab.notification.DecisionNotification;
50+
import com.optimizely.ab.notification.FeatureTestSourceInfo;
51+
import com.optimizely.ab.notification.NotificationCenter;
52+
import com.optimizely.ab.notification.NotificationHandler;
53+
import com.optimizely.ab.notification.RolloutSourceInfo;
54+
import com.optimizely.ab.notification.SourceInfo;
55+
import com.optimizely.ab.notification.TrackNotification;
56+
import com.optimizely.ab.notification.UpdateConfigNotification;
57+
import com.optimizely.ab.odp.ODPEvent;
58+
import com.optimizely.ab.odp.ODPManager;
59+
import com.optimizely.ab.odp.ODPSegmentManager;
60+
import com.optimizely.ab.odp.ODPSegmentOption;
3361
import com.optimizely.ab.optimizelyconfig.OptimizelyConfig;
3462
import com.optimizely.ab.optimizelyconfig.OptimizelyConfigManager;
3563
import com.optimizely.ab.optimizelyconfig.OptimizelyConfigService;
36-
import com.optimizely.ab.optimizelydecision.*;
64+
import com.optimizely.ab.optimizelydecision.DecisionMessage;
65+
import com.optimizely.ab.optimizelydecision.DecisionReasons;
66+
import com.optimizely.ab.optimizelydecision.DecisionResponse;
67+
import com.optimizely.ab.optimizelydecision.DefaultDecisionReasons;
68+
import com.optimizely.ab.optimizelydecision.OptimizelyDecideOption;
69+
import com.optimizely.ab.optimizelydecision.OptimizelyDecision;
3770
import com.optimizely.ab.optimizelyjson.OptimizelyJSON;
38-
import java.util.concurrent.locks.ReentrantLock;
3971
import org.slf4j.Logger;
4072
import org.slf4j.LoggerFactory;
4173

4274
import javax.annotation.Nonnull;
4375
import javax.annotation.Nullable;
4476
import javax.annotation.concurrent.ThreadSafe;
45-
4677
import java.io.Closeable;
47-
import java.util.*;
48-
import java.util.stream.Collectors;
78+
import java.util.ArrayList;
79+
import java.util.Arrays;
80+
import java.util.Collections;
81+
import java.util.HashMap;
82+
import java.util.List;
83+
import java.util.Map;
84+
import java.util.concurrent.locks.ReentrantLock;
4985

5086
import static com.optimizely.ab.internal.SafetyUtils.tryClose;
5187

5288
/**
5389
* Top-level container class for Optimizely functionality.
5490
* Thread-safe, so can be created as a singleton and safely passed around.
55-
*
91+
* <p>
5692
* Example instantiation:
5793
* <pre>
5894
* Optimizely optimizely = Optimizely.builder(projectWatcher, eventHandler).build();
5995
* </pre>
60-
*
96+
* <p>
6197
* To activate an experiment and perform variation specific processing:
6298
* <pre>
6399
* Variation variation = optimizely.activate(experimentKey, userId, attributes);
@@ -136,7 +172,9 @@ private Optimizely(@Nonnull EventHandler eventHandler,
136172
if (projectConfigManager.getSDKKey() != null) {
137173
NotificationRegistry.getInternalNotificationCenter(projectConfigManager.getSDKKey()).
138174
addNotificationHandler(UpdateConfigNotification.class,
139-
configNotification -> { updateODPSettings(); });
175+
configNotification -> {
176+
updateODPSettings();
177+
});
140178
}
141179

142180
}
@@ -634,6 +672,53 @@ public Integer getFeatureVariableInteger(@Nonnull String featureKey,
634672
return variableValue;
635673
}
636674

675+
/**
676+
* Get the Long value of the specified variable in the feature.
677+
*
678+
* @param featureKey The unique key of the feature.
679+
* @param variableKey The unique key of the variable.
680+
* @param userId The ID of the user.
681+
* @return The Integer value of the integer single variable feature.
682+
* Null if the feature or variable could not be found.
683+
*/
684+
@Nullable
685+
public Long getFeatureVariableLong(@Nonnull String featureKey,
686+
@Nonnull String variableKey,
687+
@Nonnull String userId) {
688+
return getFeatureVariableLong(featureKey, variableKey, userId, Collections.emptyMap());
689+
}
690+
691+
/**
692+
* Get the Integer value of the specified variable in the feature.
693+
*
694+
* @param featureKey The unique key of the feature.
695+
* @param variableKey The unique key of the variable.
696+
* @param userId The ID of the user.
697+
* @param attributes The user's attributes.
698+
* @return The Integer value of the integer single variable feature.
699+
* Null if the feature or variable could not be found.
700+
*/
701+
@Nullable
702+
public Long getFeatureVariableLong(@Nonnull String featureKey,
703+
@Nonnull String variableKey,
704+
@Nonnull String userId,
705+
@Nonnull Map<String, ?> attributes) {
706+
try {
707+
return getFeatureVariableValueForType(
708+
featureKey,
709+
variableKey,
710+
userId,
711+
attributes,
712+
FeatureVariable.INTEGER_TYPE
713+
);
714+
715+
} catch (Exception exception) {
716+
logger.error("NumberFormatException while trying to parse value as Long. {}", String.valueOf(exception));
717+
}
718+
719+
return null;
720+
}
721+
637722
/**
638723
* Get the String value of the specified variable in the feature.
639724
*
@@ -828,8 +913,13 @@ Object convertStringToType(String variableValue, String type) {
828913
try {
829914
return Integer.parseInt(variableValue);
830915
} catch (NumberFormatException exception) {
831-
logger.error("NumberFormatException while trying to parse \"" + variableValue +
832-
"\" as Integer. " + exception.toString());
916+
try {
917+
return Long.parseLong(variableValue);
918+
} catch (NumberFormatException longException) {
919+
logger.error("NumberFormatException while trying to parse \"{}\" as Integer. {}",
920+
variableValue,
921+
exception.toString());
922+
}
833923
}
834924
break;
835925
case FeatureVariable.JSON_TYPE:
@@ -845,11 +935,10 @@ Object convertStringToType(String variableValue, String type) {
845935
/**
846936
* Get the values of all variables in the feature.
847937
*
848-
* @param featureKey The unique key of the feature.
849-
* @param userId The ID of the user.
938+
* @param featureKey The unique key of the feature.
939+
* @param userId The ID of the user.
850940
* @return An OptimizelyJSON instance for all variable values.
851941
* Null if the feature could not be found.
852-
*
853942
*/
854943
@Nullable
855944
public OptimizelyJSON getAllFeatureVariables(@Nonnull String featureKey,
@@ -860,12 +949,11 @@ public OptimizelyJSON getAllFeatureVariables(@Nonnull String featureKey,
860949
/**
861950
* Get the values of all variables in the feature.
862951
*
863-
* @param featureKey The unique key of the feature.
864-
* @param userId The ID of the user.
865-
* @param attributes The user's attributes.
952+
* @param featureKey The unique key of the feature.
953+
* @param userId The ID of the user.
954+
* @param attributes The user's attributes.
866955
* @return An OptimizelyJSON instance for all variable values.
867956
* Null if the feature could not be found.
868-
*
869957
*/
870958
@Nullable
871959
public OptimizelyJSON getAllFeatureVariables(@Nonnull String featureKey,
@@ -949,7 +1037,6 @@ public OptimizelyJSON getAllFeatureVariables(@Nonnull String featureKey,
9491037
* @param attributes The user's attributes.
9501038
* @return List of the feature keys that are enabled for the user if the userId is empty it will
9511039
* return Empty List.
952-
*
9531040
*/
9541041
public List<String> getEnabledFeatures(@Nonnull String userId, @Nonnull Map<String, ?> attributes) {
9551042
List<String> enabledFeaturesList = new ArrayList();
@@ -1164,10 +1251,10 @@ public OptimizelyConfig getOptimizelyConfig() {
11641251

11651252
/**
11661253
* Create a context of the user for which decision APIs will be called.
1167-
*
1254+
* <p>
11681255
* A user context will be created successfully even when the SDK is not fully configured yet.
11691256
*
1170-
* @param userId The user ID to be used for bucketing.
1257+
* @param userId The user ID to be used for bucketing.
11711258
* @param attributes: A map of attribute names to current user attribute values.
11721259
* @return An OptimizelyUserContext associated with this OptimizelyClient.
11731260
*/
@@ -1289,15 +1376,15 @@ private OptimizelyDecision createOptimizelyDecision(
12891376
}
12901377

12911378
Map<String, OptimizelyDecision> decideForKeys(@Nonnull OptimizelyUserContext user,
1292-
@Nonnull List<String> keys,
1293-
@Nonnull List<OptimizelyDecideOption> options) {
1379+
@Nonnull List<String> keys,
1380+
@Nonnull List<OptimizelyDecideOption> options) {
12941381
return decideForKeys(user, keys, options, false);
12951382
}
12961383

12971384
private Map<String, OptimizelyDecision> decideForKeys(@Nonnull OptimizelyUserContext user,
1298-
@Nonnull List<String> keys,
1299-
@Nonnull List<OptimizelyDecideOption> options,
1300-
boolean ignoreDefaultOptions) {
1385+
@Nonnull List<String> keys,
1386+
@Nonnull List<OptimizelyDecideOption> options,
1387+
boolean ignoreDefaultOptions) {
13011388
Map<String, OptimizelyDecision> decisionMap = new HashMap<>();
13021389

13031390
ProjectConfig projectConfig = getProjectConfig();
@@ -1308,7 +1395,7 @@ private Map<String, OptimizelyDecision> decideForKeys(@Nonnull OptimizelyUserCon
13081395

13091396
if (keys.isEmpty()) return decisionMap;
13101397

1311-
List<OptimizelyDecideOption> allOptions = ignoreDefaultOptions ? options: getAllOptions(options);
1398+
List<OptimizelyDecideOption> allOptions = ignoreDefaultOptions ? options : getAllOptions(options);
13121399

13131400
Map<String, FeatureDecision> flagDecisions = new HashMap<>();
13141401
Map<String, DecisionReasons> decisionReasonsMap = new HashMap<>();
@@ -1351,7 +1438,7 @@ private Map<String, OptimizelyDecision> decideForKeys(@Nonnull OptimizelyUserCon
13511438
decisionReasonsMap.get(flagKey).merge(decision.getReasons());
13521439
}
13531440

1354-
for (String key: validKeys) {
1441+
for (String key : validKeys) {
13551442
FeatureDecision flagDecision = flagDecisions.get(key);
13561443
DecisionReasons decisionReasons = decisionReasonsMap.get((key));
13571444

@@ -1484,9 +1571,9 @@ public int addLogEventNotificationHandler(NotificationHandler<LogEvent> handler)
14841571
/**
14851572
* Convenience method for adding NotificationHandlers
14861573
*
1487-
* @param clazz The class of NotificationHandler
1574+
* @param clazz The class of NotificationHandler
14881575
* @param handler NotificationHandler handler
1489-
* @param <T> This is the type parameter
1576+
* @param <T> This is the type parameter
14901577
* @return A handler Id (greater than 0 if succeeded)
14911578
*/
14921579
public <T> int addNotificationHandler(Class<T> clazz, NotificationHandler<T> handler) {
@@ -1535,10 +1622,10 @@ public ODPManager getODPManager() {
15351622
/**
15361623
* Send an event to the ODP server.
15371624
*
1538-
* @param type the event type (default = "fullstack").
1539-
* @param action the event action name.
1625+
* @param type the event type (default = "fullstack").
1626+
* @param action the event action name.
15401627
* @param identifiers a dictionary for identifiers. The caller must provide at least one key-value pair unless non-empty common identifiers have been set already with {@link ODPManager.Builder#withUserCommonIdentifiers(Map) }.
1541-
* @param data a dictionary for associated data. The default event data will be added to this data before sending to the ODP server.
1628+
* @param data a dictionary for associated data. The default event data will be added to this data before sending to the ODP server.
15421629
*/
15431630
public void sendODPEvent(@Nullable String type, @Nonnull String action, @Nullable Map<String, String> identifiers, @Nullable Map<String, Object> data) {
15441631
ProjectConfig projectConfig = getProjectConfig();
@@ -1586,7 +1673,7 @@ private void updateODPSettings() {
15861673
* {@link Builder#withDatafile(java.lang.String)} and
15871674
* {@link Builder#withEventHandler(com.optimizely.ab.event.EventHandler)}
15881675
* respectively.
1589-
*
1676+
* <p>
15901677
* Example:
15911678
* <pre>
15921679
* Optimizely optimizely = Optimizely.builder()
@@ -1595,7 +1682,7 @@ private void updateODPSettings() {
15951682
* .build();
15961683
* </pre>
15971684
*
1598-
* @param datafile A datafile
1685+
* @param datafile A datafile
15991686
* @param eventHandler An EventHandler
16001687
* @return An Optimizely builder
16011688
*/
@@ -1644,7 +1731,8 @@ public Builder(@Nonnull String datafile,
16441731
this.datafile = datafile;
16451732
}
16461733

1647-
public Builder() { }
1734+
public Builder() {
1735+
}
16481736

16491737
public Builder withErrorHandler(ErrorHandler errorHandler) {
16501738
this.errorHandler = errorHandler;
@@ -1686,7 +1774,7 @@ public Builder withUserProfileService(UserProfileService userProfileService) {
16861774
* Override the SDK name and version (for client SDKs like android-sdk wrapping the core java-sdk) to be included in events.
16871775
*
16881776
* @param clientEngineName the client engine name ("java-sdk", "android-sdk", "flutter-sdk", etc.).
1689-
* @param clientVersion the client SDK version.
1777+
* @param clientVersion the client SDK version.
16901778
* @return An Optimizely builder
16911779
*/
16921780
public Builder withClientInfo(String clientEngineName, String clientVersion) {

0 commit comments

Comments
 (0)