@@ -376,7 +376,7 @@ public void track(@Nonnull String eventName,
376376 @ Nonnull
377377 public Boolean isFeatureEnabled (@ Nonnull String featureKey ,
378378 @ Nonnull String userId ) {
379- return isFeatureEnabled (featureKey , userId , Collections .< String , String > emptyMap ());
379+ return isFeatureEnabled (featureKey , userId , Collections .emptyMap ());
380380 }
381381
382382 /**
@@ -424,7 +424,7 @@ private Boolean isFeatureEnabled(@Nonnull ProjectConfig projectConfig,
424424
425425 Map <String , ?> copiedAttributes = copyAttributes (attributes );
426426 FeatureDecision .DecisionSource decisionSource = FeatureDecision .DecisionSource .ROLLOUT ;
427- FeatureDecision featureDecision = decisionService .getVariationForFeature (featureFlag , userId , copiedAttributes , projectConfig ).getResult ();
427+ FeatureDecision featureDecision = decisionService .getVariationForFeature (featureFlag , createUserContext ( userId , copiedAttributes ) , projectConfig ).getResult ();
428428 Boolean featureEnabled = false ;
429429 SourceInfo sourceInfo = new RolloutSourceInfo ();
430430 if (featureDecision .decisionSource != null ) {
@@ -733,7 +733,7 @@ <T> T getFeatureVariableValueForType(@Nonnull String featureKey,
733733
734734 String variableValue = variable .getDefaultValue ();
735735 Map <String , ?> copiedAttributes = copyAttributes (attributes );
736- FeatureDecision featureDecision = decisionService .getVariationForFeature (featureFlag , userId , copiedAttributes , projectConfig ).getResult ();
736+ FeatureDecision featureDecision = decisionService .getVariationForFeature (featureFlag , createUserContext ( userId , copiedAttributes ) , projectConfig ).getResult ();
737737 Boolean featureEnabled = false ;
738738 if (featureDecision .variation != null ) {
739739 if (featureDecision .variation .getFeatureEnabled ()) {
@@ -824,6 +824,7 @@ Object convertStringToType(String variableValue, String type) {
824824 * @param userId The ID of the user.
825825 * @return An OptimizelyJSON instance for all variable values.
826826 * Null if the feature could not be found.
827+ *
827828 */
828829 @ Nullable
829830 public OptimizelyJSON getAllFeatureVariables (@ Nonnull String featureKey ,
@@ -839,6 +840,7 @@ public OptimizelyJSON getAllFeatureVariables(@Nonnull String featureKey,
839840 * @param attributes The user's attributes.
840841 * @return An OptimizelyJSON instance for all variable values.
841842 * Null if the feature could not be found.
843+ *
842844 */
843845 @ Nullable
844846 public OptimizelyJSON getAllFeatureVariables (@ Nonnull String featureKey ,
@@ -866,7 +868,7 @@ public OptimizelyJSON getAllFeatureVariables(@Nonnull String featureKey,
866868 }
867869
868870 Map <String , ?> copiedAttributes = copyAttributes (attributes );
869- FeatureDecision featureDecision = decisionService .getVariationForFeature (featureFlag , userId , copiedAttributes , projectConfig ).getResult ();
871+ FeatureDecision featureDecision = decisionService .getVariationForFeature (featureFlag , createUserContext ( userId , copiedAttributes ) , projectConfig , Collections . emptyList () ).getResult ();
870872 Boolean featureEnabled = false ;
871873 Variation variation = featureDecision .variation ;
872874
@@ -922,9 +924,10 @@ public OptimizelyJSON getAllFeatureVariables(@Nonnull String featureKey,
922924 * @param attributes The user's attributes.
923925 * @return List of the feature keys that are enabled for the user if the userId is empty it will
924926 * return Empty List.
927+ *
925928 */
926929 public List <String > getEnabledFeatures (@ Nonnull String userId , @ Nonnull Map <String , ?> attributes ) {
927- List <String > enabledFeaturesList = new ArrayList < String > ();
930+ List <String > enabledFeaturesList = new ArrayList ();
928931 if (!validateUserId (userId )) {
929932 return enabledFeaturesList ;
930933 }
@@ -951,7 +954,7 @@ public List<String> getEnabledFeatures(@Nonnull String userId, @Nonnull Map<Stri
951954 public Variation getVariation (@ Nonnull Experiment experiment ,
952955 @ Nonnull String userId ) throws UnknownExperimentException {
953956
954- return getVariation (experiment , userId , Collections .< String , String > emptyMap ());
957+ return getVariation (experiment , userId , Collections .emptyMap ());
955958 }
956959
957960 @ Nullable
@@ -967,8 +970,7 @@ private Variation getVariation(@Nonnull ProjectConfig projectConfig,
967970 @ Nonnull String userId ,
968971 @ Nonnull Map <String , ?> attributes ) throws UnknownExperimentException {
969972 Map <String , ?> copiedAttributes = copyAttributes (attributes );
970- Variation variation = decisionService .getVariation (experiment , userId , copiedAttributes , projectConfig ).getResult ();
971-
973+ Variation variation = decisionService .getVariation (experiment , createUserContext (userId , copiedAttributes ), projectConfig ).getResult ();
972974 String notificationType = NotificationCenter .DecisionNotificationType .AB_TEST .toString ();
973975
974976 if (projectConfig .getExperimentFeatureKeyMapping ().get (experiment .getId ()) != null ) {
@@ -1145,7 +1147,7 @@ public OptimizelyConfig getOptimizelyConfig() {
11451147 * @return An OptimizelyUserContext associated with this OptimizelyClient.
11461148 */
11471149 public OptimizelyUserContext createUserContext (@ Nonnull String userId ,
1148- @ Nonnull Map <String , Object > attributes ) {
1150+ @ Nonnull Map <String , ? > attributes ) {
11491151 if (userId == null ) {
11501152 logger .warn ("The userId parameter must be nonnull." );
11511153 return null ;
@@ -1179,14 +1181,24 @@ OptimizelyDecision decide(@Nonnull OptimizelyUserContext user,
11791181 DecisionReasons decisionReasons = DefaultDecisionReasons .newInstance (allOptions );
11801182
11811183 Map <String , ?> copiedAttributes = new HashMap <>(attributes );
1182- DecisionResponse <FeatureDecision > decisionVariation = decisionService .getVariationForFeature (
1183- flag ,
1184- userId ,
1185- copiedAttributes ,
1186- projectConfig ,
1187- allOptions );
1188- FeatureDecision flagDecision = decisionVariation .getResult ();
1189- decisionReasons .merge (decisionVariation .getReasons ());
1184+ FeatureDecision flagDecision ;
1185+
1186+ // Check Forced Decision
1187+ OptimizelyDecisionContext optimizelyDecisionContext = new OptimizelyDecisionContext (flag .getKey (), null );
1188+ DecisionResponse <Variation > forcedDecisionVariation = user .findValidatedForcedDecision (optimizelyDecisionContext );
1189+ decisionReasons .merge (forcedDecisionVariation .getReasons ());
1190+ if (forcedDecisionVariation .getResult () != null ) {
1191+ flagDecision = new FeatureDecision (null , forcedDecisionVariation .getResult (), FeatureDecision .DecisionSource .FEATURE_TEST );
1192+ } else {
1193+ // Regular decision
1194+ DecisionResponse <FeatureDecision > decisionVariation = decisionService .getVariationForFeature (
1195+ flag ,
1196+ user ,
1197+ projectConfig ,
1198+ allOptions );
1199+ flagDecision = decisionVariation .getResult ();
1200+ decisionReasons .merge (decisionVariation .getReasons ());
1201+ }
11901202
11911203 Boolean flagEnabled = false ;
11921204 if (flagDecision .variation != null ) {
@@ -1332,6 +1344,26 @@ private DecisionResponse<Map<String, Object>> getDecisionVariableMap(@Nonnull Fe
13321344 return new DecisionResponse (valuesMap , reasons );
13331345 }
13341346
1347+ /**
1348+ * Gets a variation based on flagKey and variationKey
1349+ *
1350+ * @param flagKey The flag key for the variation
1351+ * @param variationKey The variation key for the variation
1352+ * @return Returns a variation based on flagKey and variationKey, otherwise null
1353+ */
1354+ public Variation getFlagVariationByKey (String flagKey , String variationKey ) {
1355+ Map <String , List <Variation >> flagVariationsMap = getProjectConfig ().getFlagVariationsMap ();
1356+ if (flagVariationsMap .containsKey (flagKey )) {
1357+ List <Variation > variations = flagVariationsMap .get (flagKey );
1358+ for (Variation variation : variations ) {
1359+ if (variation .getKey ().equals (variationKey )) {
1360+ return variation ;
1361+ }
1362+ }
1363+ }
1364+ return null ;
1365+ }
1366+
13351367 /**
13361368 * Helper method which makes separate copy of attributesMap variable and returns it
13371369 *
0 commit comments