diff --git a/core-api/src/main/java/com/optimizely/ab/Optimizely.java b/core-api/src/main/java/com/optimizely/ab/Optimizely.java index aff6db441..b9a294670 100644 --- a/core-api/src/main/java/com/optimizely/ab/Optimizely.java +++ b/core-api/src/main/java/com/optimizely/ab/Optimizely.java @@ -35,8 +35,7 @@ import com.optimizely.ab.event.internal.BuildVersionInfo; import com.optimizely.ab.event.internal.EventFactory; import com.optimizely.ab.event.internal.payload.EventBatch.ClientEngine; -import com.optimizely.ab.notification.DecisionNotification; -import com.optimizely.ab.notification.NotificationCenter; +import com.optimizely.ab.notification.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -388,11 +387,10 @@ public Boolean isFeatureEnabled(@Nonnull String featureKey, Map copiedAttributes = copyAttributes(attributes); FeatureDecision.DecisionSource decisionSource = FeatureDecision.DecisionSource.ROLLOUT; - String sourceExperimentKey = null; - String sourceVariationKey = null; FeatureDecision featureDecision = decisionService.getVariationForFeature(featureFlag, userId, copiedAttributes); Boolean featureEnabled = false; + SourceInfo sourceInfo = new RolloutSourceInfo(); if (featureDecision.variation != null) { if (featureDecision.decisionSource.equals(FeatureDecision.DecisionSource.FEATURE_TEST)) { sendImpression( @@ -402,8 +400,7 @@ public Boolean isFeatureEnabled(@Nonnull String featureKey, copiedAttributes, featureDecision.variation); decisionSource = featureDecision.decisionSource; - sourceVariationKey = featureDecision.variation.getKey(); - sourceExperimentKey = featureDecision.experiment.getKey(); + sourceInfo = new FeatureTestSourceInfo(featureDecision.experiment.getKey(), featureDecision.variation.getKey()); } else { logger.info("The user \"{}\" is not included in an experiment for feature \"{}\".", userId, featureKey); @@ -420,8 +417,7 @@ public Boolean isFeatureEnabled(@Nonnull String featureKey, .withFeatureKey(featureKey) .withFeatureEnabled(featureEnabled) .withSource(decisionSource) - .withExperimentKey(sourceExperimentKey) - .withVariationKey(sourceVariationKey) + .withSourceInfo(sourceInfo) .build(); notificationCenter.sendNotifications(decisionNotification); diff --git a/core-api/src/main/java/com/optimizely/ab/notification/DecisionNotification.java b/core-api/src/main/java/com/optimizely/ab/notification/DecisionNotification.java index 1bcb88599..414eb393d 100644 --- a/core-api/src/main/java/com/optimizely/ab/notification/DecisionNotification.java +++ b/core-api/src/main/java/com/optimizely/ab/notification/DecisionNotification.java @@ -26,6 +26,9 @@ import java.util.HashMap; import java.util.Map; +import static com.optimizely.ab.notification.DecisionNotification.ExperimentDecisionNotificationBuilder.EXPERIMENT_KEY; +import static com.optimizely.ab.notification.DecisionNotification.ExperimentDecisionNotificationBuilder.VARIATION_KEY; + public class DecisionNotification { protected String type; protected String userId; @@ -126,13 +129,10 @@ public static class FeatureDecisionNotificationBuilder { public final static String FEATURE_ENABLED = "featureEnabled"; public final static String SOURCE = "source"; public final static String SOURCE_INFO = "sourceInfo"; - public final static String EXPERIMENT_KEY = "experimentKey"; - public final static String VARIATION_KEY = "variationKey"; private String featureKey; private Boolean featureEnabled; - private String experimentKey; - private String variationKey; + private SourceInfo sourceInfo; private FeatureDecision.DecisionSource source; private String userId; private Map attributes; @@ -148,13 +148,8 @@ public FeatureDecisionNotificationBuilder withAttributes(Map attribut return this; } - public FeatureDecisionNotificationBuilder withExperimentKey(String experimentKey) { - this.experimentKey = experimentKey; - return this; - } - - public FeatureDecisionNotificationBuilder withVariationKey(String variationKey) { - this.variationKey = variationKey; + public FeatureDecisionNotificationBuilder withSourceInfo(SourceInfo sourceInfo) { + this.sourceInfo = sourceInfo; return this; } @@ -179,12 +174,7 @@ public DecisionNotification build() { decisionInfo.put(FEATURE_ENABLED, featureEnabled); decisionInfo.put(SOURCE, source.toString()); - Map sourceInfo = new HashMap<>(); - if (source.equals(FeatureDecision.DecisionSource.FEATURE_TEST)) { - sourceInfo.put(EXPERIMENT_KEY, experimentKey); - sourceInfo.put(VARIATION_KEY, variationKey); - } - decisionInfo.put(SOURCE_INFO, sourceInfo); + decisionInfo.put(SOURCE_INFO, sourceInfo.get()); return new DecisionNotification( NotificationCenter.DecisionNotificationType.FEATURE.toString(), @@ -204,8 +194,6 @@ public static class FeatureVariableDecisionNotificationBuilder { public static final String FEATURE_ENABLED = "featureEnabled"; public static final String SOURCE = "source"; public static final String SOURCE_INFO = "sourceInfo"; - public static final String EXPERIMENT_KEY = "experimentKey"; - public static final String VARIATION_KEY = "variationKey"; public static final String VARIABLE_KEY = "variableKey"; public static final String VARIABLE_TYPE = "variableType"; public static final String VARIABLE_VALUE = "variableValue"; @@ -270,15 +258,15 @@ public DecisionNotification build() { decisionInfo.put(VARIABLE_KEY, variableKey); decisionInfo.put(VARIABLE_TYPE, variableType); decisionInfo.put(VARIABLE_VALUE, variableValue); - Map sourceInfo = new HashMap<>(); + SourceInfo sourceInfo = new RolloutSourceInfo(); + if (featureDecision != null && FeatureDecision.DecisionSource.FEATURE_TEST.equals(featureDecision.decisionSource)) { - sourceInfo.put(EXPERIMENT_KEY, featureDecision.experiment.getKey()); - sourceInfo.put(VARIATION_KEY, featureDecision.variation.getKey()); + sourceInfo = new FeatureTestSourceInfo(featureDecision.experiment.getKey(), featureDecision.variation.getKey()); decisionInfo.put(SOURCE, featureDecision.decisionSource.toString()); } else { decisionInfo.put(SOURCE, FeatureDecision.DecisionSource.ROLLOUT.toString()); } - decisionInfo.put(SOURCE_INFO, sourceInfo); + decisionInfo.put(SOURCE_INFO, sourceInfo.get()); return new DecisionNotification( NotificationCenter.DecisionNotificationType.FEATURE_VARIABLE.toString(), diff --git a/core-api/src/main/java/com/optimizely/ab/notification/FeatureTestSourceInfo.java b/core-api/src/main/java/com/optimizely/ab/notification/FeatureTestSourceInfo.java new file mode 100644 index 000000000..55f89ec08 --- /dev/null +++ b/core-api/src/main/java/com/optimizely/ab/notification/FeatureTestSourceInfo.java @@ -0,0 +1,42 @@ +/**************************************************************************** + * Copyright 2019, Optimizely, Inc. and contributors * + * * + * Licensed under the Apache License, Version 2.0 (the "License"); * + * you may not use this file except in compliance with the License. * + * You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, software * + * distributed under the License is distributed on an "AS IS" BASIS, * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * + * See the License for the specific language governing permissions and * + * limitations under the License. * + ***************************************************************************/ + +package com.optimizely.ab.notification; + +import java.util.HashMap; +import java.util.Map; + +import static com.optimizely.ab.notification.DecisionNotification.ExperimentDecisionNotificationBuilder.EXPERIMENT_KEY; +import static com.optimizely.ab.notification.DecisionNotification.ExperimentDecisionNotificationBuilder.VARIATION_KEY; + +public class FeatureTestSourceInfo implements SourceInfo { + private String experimentKey; + private String variationKey; + + public FeatureTestSourceInfo(String experimentKey, String variationKey) { + this.experimentKey = experimentKey; + this.variationKey = variationKey; + } + + @Override + public Map get() { + Map sourceInfo = new HashMap<>(); + sourceInfo.put(EXPERIMENT_KEY, experimentKey); + sourceInfo.put(VARIATION_KEY, variationKey); + + return sourceInfo; + } +} diff --git a/core-api/src/main/java/com/optimizely/ab/notification/RolloutSourceInfo.java b/core-api/src/main/java/com/optimizely/ab/notification/RolloutSourceInfo.java new file mode 100644 index 000000000..3c73c8dea --- /dev/null +++ b/core-api/src/main/java/com/optimizely/ab/notification/RolloutSourceInfo.java @@ -0,0 +1,27 @@ +/**************************************************************************** + * Copyright 2019, Optimizely, Inc. and contributors * + * * + * Licensed under the Apache License, Version 2.0 (the "License"); * + * you may not use this file except in compliance with the License. * + * You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, software * + * distributed under the License is distributed on an "AS IS" BASIS, * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * + * See the License for the specific language governing permissions and * + * limitations under the License. * + ***************************************************************************/ + +package com.optimizely.ab.notification; + +import java.util.Collections; +import java.util.Map; + +public class RolloutSourceInfo implements SourceInfo { + @Override + public Map get() { + return Collections.EMPTY_MAP; + } +} diff --git a/core-api/src/main/java/com/optimizely/ab/notification/SourceInfo.java b/core-api/src/main/java/com/optimizely/ab/notification/SourceInfo.java new file mode 100644 index 000000000..e17a4e566 --- /dev/null +++ b/core-api/src/main/java/com/optimizely/ab/notification/SourceInfo.java @@ -0,0 +1,23 @@ +/**************************************************************************** + * Copyright 2019, Optimizely, Inc. and contributors * + * * + * Licensed under the Apache License, Version 2.0 (the "License"); * + * you may not use this file except in compliance with the License. * + * You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, software * + * distributed under the License is distributed on an "AS IS" BASIS, * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * + * See the License for the specific language governing permissions and * + * limitations under the License. * + ***************************************************************************/ + +package com.optimizely.ab.notification; + +import java.util.Map; + +public interface SourceInfo { + Map get(); +} diff --git a/core-api/src/test/java/com/optimizely/ab/OptimizelyTest.java b/core-api/src/test/java/com/optimizely/ab/OptimizelyTest.java index ab81c6cd1..4e482eab7 100644 --- a/core-api/src/test/java/com/optimizely/ab/OptimizelyTest.java +++ b/core-api/src/test/java/com/optimizely/ab/OptimizelyTest.java @@ -66,6 +66,8 @@ import static com.optimizely.ab.config.ProjectConfigTestUtils.*; import static com.optimizely.ab.config.ValidProjectConfigV4.*; import static com.optimizely.ab.event.LogEvent.RequestMethod; +import static com.optimizely.ab.notification.DecisionNotification.ExperimentDecisionNotificationBuilder.EXPERIMENT_KEY; +import static com.optimizely.ab.notification.DecisionNotification.ExperimentDecisionNotificationBuilder.VARIATION_KEY; import static com.optimizely.ab.notification.DecisionNotification.FeatureVariableDecisionNotificationBuilder.*; import static java.util.Arrays.asList; import static junit.framework.TestCase.assertTrue;