diff --git a/core-api/src/jmh/java/com/optimizely/ab/BenchmarkUtils.java b/core-api/src/jmh/java/com/optimizely/ab/BenchmarkUtils.java index a4b1b1ad3..8028a6830 100644 --- a/core-api/src/jmh/java/com/optimizely/ab/BenchmarkUtils.java +++ b/core-api/src/jmh/java/com/optimizely/ab/BenchmarkUtils.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/jmh/java/com/optimizely/ab/OptimizelyBenchmark.java b/core-api/src/jmh/java/com/optimizely/ab/OptimizelyBenchmark.java index 631cf62f4..1e902f473 100644 --- a/core-api/src/jmh/java/com/optimizely/ab/OptimizelyBenchmark.java +++ b/core-api/src/jmh/java/com/optimizely/ab/OptimizelyBenchmark.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/jmh/java/com/optimizely/ab/OptimizelyBuilderBenchmark.java b/core-api/src/jmh/java/com/optimizely/ab/OptimizelyBuilderBenchmark.java index 5d9302dbc..596597f1b 100644 --- a/core-api/src/jmh/java/com/optimizely/ab/OptimizelyBuilderBenchmark.java +++ b/core-api/src/jmh/java/com/optimizely/ab/OptimizelyBuilderBenchmark.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. 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 274ec2525..a3d30261b 100644 --- a/core-api/src/main/java/com/optimizely/ab/Optimizely.java +++ b/core-api/src/main/java/com/optimizely/ab/Optimizely.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -38,7 +38,9 @@ import com.optimizely.ab.event.internal.EventBuilderV1; import com.optimizely.ab.event.internal.EventBuilderV2; import com.optimizely.ab.event.internal.payload.Event.ClientEngine; +import com.optimizely.ab.internal.EventTagUtils; import com.optimizely.ab.internal.ProjectValidationUtils; +import com.optimizely.ab.internal.ReservedEventKey; import com.optimizely.ab.notification.NotificationListener; import com.optimizely.ab.notification.NotificationBroadcaster; @@ -117,22 +119,9 @@ private Optimizely(@Nonnull ProjectConfig projectConfig, return activate(experimentKey, userId, Collections.emptyMap()); } - public @Nullable Variation activate(@Nonnull String experimentKey, - @Nonnull String userId, - @CheckForNull String sessionId) throws UnknownExperimentException { - return activate(experimentKey, userId, Collections.emptyMap(), sessionId); - } - public @Nullable Variation activate(@Nonnull String experimentKey, @Nonnull String userId, @Nonnull Map attributes) throws UnknownExperimentException { - return activate(experimentKey, userId, attributes, null); - } - - public @Nullable Variation activate(@Nonnull String experimentKey, - @Nonnull String userId, - @Nonnull Map attributes, - @CheckForNull String sessionId) throws UnknownExperimentException { if (!validateUserId(userId)) { logger.info("Not activating user for experiment \"{}\".", experimentKey); @@ -148,7 +137,7 @@ private Optimizely(@Nonnull ProjectConfig projectConfig, return null; } - return activate(currentConfig, experiment, userId, attributes, sessionId); + return activate(currentConfig, experiment, userId, attributes); } public @Nullable Variation activate(@Nonnull Experiment experiment, @@ -156,34 +145,19 @@ private Optimizely(@Nonnull ProjectConfig projectConfig, return activate(experiment, userId, Collections.emptyMap()); } - public @Nullable Variation activate(@Nonnull Experiment experiment, - @Nonnull String userId, - @CheckForNull String sessionId) { - return activate(experiment, userId, Collections.emptyMap(), sessionId); - } - public @Nullable Variation activate(@Nonnull Experiment experiment, @Nonnull String userId, @Nonnull Map attributes) { - return activate(experiment, userId, attributes, null); - } - - public @Nullable Variation activate(@Nonnull Experiment experiment, - @Nonnull String userId, - @Nonnull Map attributes, - @CheckForNull String sessionId) { - ProjectConfig currentConfig = getProjectConfig(); - return activate(currentConfig, experiment, userId, attributes, sessionId); + return activate(currentConfig, experiment, userId, attributes); } private @Nullable Variation activate(@Nonnull ProjectConfig projectConfig, @Nonnull Experiment experiment, @Nonnull String userId, - @Nonnull Map attributes, - @CheckForNull String sessionId) { + @Nonnull Map attributes) { // determine whether all the given attributes are present in the project config. If not, filter out the unknown // attributes. attributes = filterAttributes(projectConfig, attributes); @@ -202,7 +176,7 @@ private Optimizely(@Nonnull ProjectConfig projectConfig, if (experiment.isRunning()) { LogEvent impressionEvent = eventBuilder.createImpressionEvent(projectConfig, experiment, variation, userId, - attributes, sessionId); + attributes); logger.info("Activating user \"{}\" in experiment \"{}\".", userId, experiment.getKey()); logger.debug( "Dispatching impression event to URL {} with params {} and payload \"{}\".", @@ -225,61 +199,39 @@ private Optimizely(@Nonnull ProjectConfig projectConfig, public void track(@Nonnull String eventName, @Nonnull String userId) throws UnknownEventTypeException { - track(eventName, userId, Collections.emptyMap(), null, null); - } - - public void track(@Nonnull String eventName, - @Nonnull String userId, - @CheckForNull String sessionId) throws UnknownEventTypeException { - track(eventName, userId, Collections.emptyMap(), null, sessionId); + track(eventName, userId, Collections.emptyMap(), Collections.emptyMap()); } public void track(@Nonnull String eventName, @Nonnull String userId, @Nonnull Map attributes) throws UnknownEventTypeException { - track(eventName, userId, attributes, null, null); - } - - public void track(@Nonnull String eventName, - @Nonnull String userId, - @Nonnull Map attributes, - @CheckForNull String sessionId) throws UnknownEventTypeException { - track(eventName, userId, attributes, null, sessionId); + track(eventName, userId, attributes, Collections.emptyMap()); } + /** + * @deprecated see {@link #track(String, String, Map)} and pass in the revenue value as an event tag instead. + */ public void track(@Nonnull String eventName, @Nonnull String userId, long eventValue) throws UnknownEventTypeException { - track(eventName, userId, Collections.emptyMap(), eventValue); - } - - public void track(@Nonnull String eventName, - @Nonnull String userId, - long eventValue, - @CheckForNull String sessionId) throws UnknownEventTypeException { - track(eventName, userId, Collections.emptyMap(), eventValue, sessionId); + track(eventName, userId, Collections.emptyMap(), Collections.singletonMap( + ReservedEventKey.REVENUE.toString(), eventValue)); } + /** + * @deprecated see {@link #track(String, String, Map, long)} and pass in the revenue value as an event tag instead. + */ public void track(@Nonnull String eventName, @Nonnull String userId, @Nonnull Map attributes, long eventValue) throws UnknownEventTypeException { - track(eventName, userId, attributes, (Long)eventValue, null); + track(eventName, userId, attributes, Collections.singletonMap(ReservedEventKey.REVENUE.toString(), eventValue)); } public void track(@Nonnull String eventName, - @Nonnull String userId, - @Nonnull Map attributes, - long eventValue, - @CheckForNull String sessionId) throws UnknownEventTypeException { - track(eventName, userId, attributes, (Long)eventValue, sessionId); - } - - private void track(@Nonnull String eventName, @Nonnull String userId, @Nonnull Map attributes, - @CheckForNull Long eventValue, - @CheckForNull String sessionId) throws UnknownEventTypeException { + @Nonnull Map eventTags) throws UnknownEventTypeException { ProjectConfig currentConfig = getProjectConfig(); @@ -294,10 +246,18 @@ private void track(@Nonnull String eventName, // attributes. attributes = filterAttributes(currentConfig, attributes); + Long eventValue = null; + if (eventTags == null) { + logger.warn("Event tags is null when non-null was expected. Defaulting to an empty event tags map."); + eventTags = Collections.emptyMap(); + } else { + eventValue = EventTagUtils.getRevenueValue(eventTags); + } + // create the conversion event request parameters, then dispatch LogEvent conversionEvent = eventBuilder.createConversionEvent(currentConfig, bucketer, userId, eventType.getId(), eventType.getKey(), attributes, - eventValue, sessionId); + eventTags); if (conversionEvent == null) { logger.info("There are no valid experiments for event \"{}\" to track.", eventName); diff --git a/core-api/src/main/java/com/optimizely/ab/OptimizelyRuntimeException.java b/core-api/src/main/java/com/optimizely/ab/OptimizelyRuntimeException.java index 1ab3780ef..f61ac0fae 100644 --- a/core-api/src/main/java/com/optimizely/ab/OptimizelyRuntimeException.java +++ b/core-api/src/main/java/com/optimizely/ab/OptimizelyRuntimeException.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/UnknownEventTypeException.java b/core-api/src/main/java/com/optimizely/ab/UnknownEventTypeException.java index 75b0c1f16..9375b35e2 100644 --- a/core-api/src/main/java/com/optimizely/ab/UnknownEventTypeException.java +++ b/core-api/src/main/java/com/optimizely/ab/UnknownEventTypeException.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/UnknownExperimentException.java b/core-api/src/main/java/com/optimizely/ab/UnknownExperimentException.java index 8b5399781..01a9aa774 100644 --- a/core-api/src/main/java/com/optimizely/ab/UnknownExperimentException.java +++ b/core-api/src/main/java/com/optimizely/ab/UnknownExperimentException.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/UnknownLiveVariableException.java b/core-api/src/main/java/com/optimizely/ab/UnknownLiveVariableException.java index ac14587c2..bd8e0989b 100644 --- a/core-api/src/main/java/com/optimizely/ab/UnknownLiveVariableException.java +++ b/core-api/src/main/java/com/optimizely/ab/UnknownLiveVariableException.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/annotations/VisibleForTesting.java b/core-api/src/main/java/com/optimizely/ab/annotations/VisibleForTesting.java index f190684df..4dc0bae67 100644 --- a/core-api/src/main/java/com/optimizely/ab/annotations/VisibleForTesting.java +++ b/core-api/src/main/java/com/optimizely/ab/annotations/VisibleForTesting.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/bucketing/Bucketer.java b/core-api/src/main/java/com/optimizely/ab/bucketing/Bucketer.java index b7199a113..c1f1c7cef 100644 --- a/core-api/src/main/java/com/optimizely/ab/bucketing/Bucketer.java +++ b/core-api/src/main/java/com/optimizely/ab/bucketing/Bucketer.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/bucketing/UserProfile.java b/core-api/src/main/java/com/optimizely/ab/bucketing/UserProfile.java index c5405d9ae..8238bf1c2 100644 --- a/core-api/src/main/java/com/optimizely/ab/bucketing/UserProfile.java +++ b/core-api/src/main/java/com/optimizely/ab/bucketing/UserProfile.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/bucketing/internal/MurmurHash3.java b/core-api/src/main/java/com/optimizely/ab/bucketing/internal/MurmurHash3.java index e4f09747d..93e706f3f 100644 --- a/core-api/src/main/java/com/optimizely/ab/bucketing/internal/MurmurHash3.java +++ b/core-api/src/main/java/com/optimizely/ab/bucketing/internal/MurmurHash3.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/config/Attribute.java b/core-api/src/main/java/com/optimizely/ab/config/Attribute.java index 6d2702982..5bb6698bc 100644 --- a/core-api/src/main/java/com/optimizely/ab/config/Attribute.java +++ b/core-api/src/main/java/com/optimizely/ab/config/Attribute.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/config/EventType.java b/core-api/src/main/java/com/optimizely/ab/config/EventType.java index b0c0bb455..961d15392 100644 --- a/core-api/src/main/java/com/optimizely/ab/config/EventType.java +++ b/core-api/src/main/java/com/optimizely/ab/config/EventType.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/config/Experiment.java b/core-api/src/main/java/com/optimizely/ab/config/Experiment.java index b8bfc99e9..f82e78903 100644 --- a/core-api/src/main/java/com/optimizely/ab/config/Experiment.java +++ b/core-api/src/main/java/com/optimizely/ab/config/Experiment.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/config/Group.java b/core-api/src/main/java/com/optimizely/ab/config/Group.java index 0dc01820d..cd41bc120 100644 --- a/core-api/src/main/java/com/optimizely/ab/config/Group.java +++ b/core-api/src/main/java/com/optimizely/ab/config/Group.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/config/IdKeyMapped.java b/core-api/src/main/java/com/optimizely/ab/config/IdKeyMapped.java index c9331c83f..3e7578d77 100644 --- a/core-api/src/main/java/com/optimizely/ab/config/IdKeyMapped.java +++ b/core-api/src/main/java/com/optimizely/ab/config/IdKeyMapped.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/config/IdMapped.java b/core-api/src/main/java/com/optimizely/ab/config/IdMapped.java index 88828bb6a..0a032c7c8 100644 --- a/core-api/src/main/java/com/optimizely/ab/config/IdMapped.java +++ b/core-api/src/main/java/com/optimizely/ab/config/IdMapped.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/config/LiveVariable.java b/core-api/src/main/java/com/optimizely/ab/config/LiveVariable.java index 0937e1ecd..4f6049282 100644 --- a/core-api/src/main/java/com/optimizely/ab/config/LiveVariable.java +++ b/core-api/src/main/java/com/optimizely/ab/config/LiveVariable.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/config/LiveVariableUsageInstance.java b/core-api/src/main/java/com/optimizely/ab/config/LiveVariableUsageInstance.java index be54a05e0..05378b808 100644 --- a/core-api/src/main/java/com/optimizely/ab/config/LiveVariableUsageInstance.java +++ b/core-api/src/main/java/com/optimizely/ab/config/LiveVariableUsageInstance.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/config/ProjectConfig.java b/core-api/src/main/java/com/optimizely/ab/config/ProjectConfig.java index 254b70963..9f7b6b292 100644 --- a/core-api/src/main/java/com/optimizely/ab/config/ProjectConfig.java +++ b/core-api/src/main/java/com/optimizely/ab/config/ProjectConfig.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/config/ProjectConfigUtils.java b/core-api/src/main/java/com/optimizely/ab/config/ProjectConfigUtils.java index 7dde59fca..84cf6cab1 100644 --- a/core-api/src/main/java/com/optimizely/ab/config/ProjectConfigUtils.java +++ b/core-api/src/main/java/com/optimizely/ab/config/ProjectConfigUtils.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/config/TrafficAllocation.java b/core-api/src/main/java/com/optimizely/ab/config/TrafficAllocation.java index 2a6b4c9e7..a66cfb81a 100644 --- a/core-api/src/main/java/com/optimizely/ab/config/TrafficAllocation.java +++ b/core-api/src/main/java/com/optimizely/ab/config/TrafficAllocation.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/config/Variation.java b/core-api/src/main/java/com/optimizely/ab/config/Variation.java index 9a31a8fb8..0991a0a5e 100644 --- a/core-api/src/main/java/com/optimizely/ab/config/Variation.java +++ b/core-api/src/main/java/com/optimizely/ab/config/Variation.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/config/audience/AndCondition.java b/core-api/src/main/java/com/optimizely/ab/config/audience/AndCondition.java index 49754b2d8..b734f8a9c 100644 --- a/core-api/src/main/java/com/optimizely/ab/config/audience/AndCondition.java +++ b/core-api/src/main/java/com/optimizely/ab/config/audience/AndCondition.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/config/audience/Audience.java b/core-api/src/main/java/com/optimizely/ab/config/audience/Audience.java index 8f4578b5e..dfb6c26a5 100644 --- a/core-api/src/main/java/com/optimizely/ab/config/audience/Audience.java +++ b/core-api/src/main/java/com/optimizely/ab/config/audience/Audience.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/config/audience/Condition.java b/core-api/src/main/java/com/optimizely/ab/config/audience/Condition.java index c77080231..3a47453e4 100644 --- a/core-api/src/main/java/com/optimizely/ab/config/audience/Condition.java +++ b/core-api/src/main/java/com/optimizely/ab/config/audience/Condition.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/config/audience/NotCondition.java b/core-api/src/main/java/com/optimizely/ab/config/audience/NotCondition.java index c342776d9..7e269c6f3 100644 --- a/core-api/src/main/java/com/optimizely/ab/config/audience/NotCondition.java +++ b/core-api/src/main/java/com/optimizely/ab/config/audience/NotCondition.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/config/audience/OrCondition.java b/core-api/src/main/java/com/optimizely/ab/config/audience/OrCondition.java index 9710962d2..c7a85556e 100644 --- a/core-api/src/main/java/com/optimizely/ab/config/audience/OrCondition.java +++ b/core-api/src/main/java/com/optimizely/ab/config/audience/OrCondition.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/config/audience/UserAttribute.java b/core-api/src/main/java/com/optimizely/ab/config/audience/UserAttribute.java index 2568a8609..34e49b0bb 100644 --- a/core-api/src/main/java/com/optimizely/ab/config/audience/UserAttribute.java +++ b/core-api/src/main/java/com/optimizely/ab/config/audience/UserAttribute.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/config/parser/AudienceGsonDeserializer.java b/core-api/src/main/java/com/optimizely/ab/config/parser/AudienceGsonDeserializer.java index 0066d7496..8158aeb4b 100644 --- a/core-api/src/main/java/com/optimizely/ab/config/parser/AudienceGsonDeserializer.java +++ b/core-api/src/main/java/com/optimizely/ab/config/parser/AudienceGsonDeserializer.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/config/parser/AudienceJacksonDeserializer.java b/core-api/src/main/java/com/optimizely/ab/config/parser/AudienceJacksonDeserializer.java index 6fde7aafc..1d0efc3e7 100644 --- a/core-api/src/main/java/com/optimizely/ab/config/parser/AudienceJacksonDeserializer.java +++ b/core-api/src/main/java/com/optimizely/ab/config/parser/AudienceJacksonDeserializer.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/config/parser/ConfigParseException.java b/core-api/src/main/java/com/optimizely/ab/config/parser/ConfigParseException.java index 58ff40350..a85ca5d15 100644 --- a/core-api/src/main/java/com/optimizely/ab/config/parser/ConfigParseException.java +++ b/core-api/src/main/java/com/optimizely/ab/config/parser/ConfigParseException.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/config/parser/ConfigParser.java b/core-api/src/main/java/com/optimizely/ab/config/parser/ConfigParser.java index 466821273..eb24b68f3 100644 --- a/core-api/src/main/java/com/optimizely/ab/config/parser/ConfigParser.java +++ b/core-api/src/main/java/com/optimizely/ab/config/parser/ConfigParser.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/config/parser/DefaultConfigParser.java b/core-api/src/main/java/com/optimizely/ab/config/parser/DefaultConfigParser.java index 9530f2c7b..2d19dfb28 100644 --- a/core-api/src/main/java/com/optimizely/ab/config/parser/DefaultConfigParser.java +++ b/core-api/src/main/java/com/optimizely/ab/config/parser/DefaultConfigParser.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/config/parser/ExperimentGsonDeserializer.java b/core-api/src/main/java/com/optimizely/ab/config/parser/ExperimentGsonDeserializer.java index 695a63b5b..6eea6be21 100644 --- a/core-api/src/main/java/com/optimizely/ab/config/parser/ExperimentGsonDeserializer.java +++ b/core-api/src/main/java/com/optimizely/ab/config/parser/ExperimentGsonDeserializer.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/config/parser/GroupGsonDeserializer.java b/core-api/src/main/java/com/optimizely/ab/config/parser/GroupGsonDeserializer.java index c153c34c8..05959a464 100644 --- a/core-api/src/main/java/com/optimizely/ab/config/parser/GroupGsonDeserializer.java +++ b/core-api/src/main/java/com/optimizely/ab/config/parser/GroupGsonDeserializer.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/config/parser/GroupJacksonDeserializer.java b/core-api/src/main/java/com/optimizely/ab/config/parser/GroupJacksonDeserializer.java index b7957de8d..714326fcc 100644 --- a/core-api/src/main/java/com/optimizely/ab/config/parser/GroupJacksonDeserializer.java +++ b/core-api/src/main/java/com/optimizely/ab/config/parser/GroupJacksonDeserializer.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/config/parser/GsonConfigParser.java b/core-api/src/main/java/com/optimizely/ab/config/parser/GsonConfigParser.java index 9bfa58981..b87c0a16a 100644 --- a/core-api/src/main/java/com/optimizely/ab/config/parser/GsonConfigParser.java +++ b/core-api/src/main/java/com/optimizely/ab/config/parser/GsonConfigParser.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/config/parser/GsonHelpers.java b/core-api/src/main/java/com/optimizely/ab/config/parser/GsonHelpers.java index 0031a4098..7ebdb02d2 100644 --- a/core-api/src/main/java/com/optimizely/ab/config/parser/GsonHelpers.java +++ b/core-api/src/main/java/com/optimizely/ab/config/parser/GsonHelpers.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/config/parser/JacksonConfigParser.java b/core-api/src/main/java/com/optimizely/ab/config/parser/JacksonConfigParser.java index 2e90c49ed..67ab86771 100644 --- a/core-api/src/main/java/com/optimizely/ab/config/parser/JacksonConfigParser.java +++ b/core-api/src/main/java/com/optimizely/ab/config/parser/JacksonConfigParser.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/config/parser/JsonConfigParser.java b/core-api/src/main/java/com/optimizely/ab/config/parser/JsonConfigParser.java index a614ae6ef..56dc808d2 100644 --- a/core-api/src/main/java/com/optimizely/ab/config/parser/JsonConfigParser.java +++ b/core-api/src/main/java/com/optimizely/ab/config/parser/JsonConfigParser.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/config/parser/JsonSimpleConfigParser.java b/core-api/src/main/java/com/optimizely/ab/config/parser/JsonSimpleConfigParser.java index d0bbd435a..5ac5552ee 100644 --- a/core-api/src/main/java/com/optimizely/ab/config/parser/JsonSimpleConfigParser.java +++ b/core-api/src/main/java/com/optimizely/ab/config/parser/JsonSimpleConfigParser.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/config/parser/MissingJsonParserException.java b/core-api/src/main/java/com/optimizely/ab/config/parser/MissingJsonParserException.java index 41c173d6c..a07539713 100644 --- a/core-api/src/main/java/com/optimizely/ab/config/parser/MissingJsonParserException.java +++ b/core-api/src/main/java/com/optimizely/ab/config/parser/MissingJsonParserException.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/config/parser/ProjectConfigGsonDeserializer.java b/core-api/src/main/java/com/optimizely/ab/config/parser/ProjectConfigGsonDeserializer.java index 6b43fc281..7403f0031 100644 --- a/core-api/src/main/java/com/optimizely/ab/config/parser/ProjectConfigGsonDeserializer.java +++ b/core-api/src/main/java/com/optimizely/ab/config/parser/ProjectConfigGsonDeserializer.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/config/parser/ProjectConfigJacksonDeserializer.java b/core-api/src/main/java/com/optimizely/ab/config/parser/ProjectConfigJacksonDeserializer.java index 7ae04077b..38c844457 100644 --- a/core-api/src/main/java/com/optimizely/ab/config/parser/ProjectConfigJacksonDeserializer.java +++ b/core-api/src/main/java/com/optimizely/ab/config/parser/ProjectConfigJacksonDeserializer.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/error/ErrorHandler.java b/core-api/src/main/java/com/optimizely/ab/error/ErrorHandler.java index a5e74fa37..f38ee8db9 100644 --- a/core-api/src/main/java/com/optimizely/ab/error/ErrorHandler.java +++ b/core-api/src/main/java/com/optimizely/ab/error/ErrorHandler.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/error/NoOpErrorHandler.java b/core-api/src/main/java/com/optimizely/ab/error/NoOpErrorHandler.java index fc3318941..ef763a21f 100644 --- a/core-api/src/main/java/com/optimizely/ab/error/NoOpErrorHandler.java +++ b/core-api/src/main/java/com/optimizely/ab/error/NoOpErrorHandler.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/error/RaiseExceptionErrorHandler.java b/core-api/src/main/java/com/optimizely/ab/error/RaiseExceptionErrorHandler.java index 87ace738d..9aa6f17c1 100644 --- a/core-api/src/main/java/com/optimizely/ab/error/RaiseExceptionErrorHandler.java +++ b/core-api/src/main/java/com/optimizely/ab/error/RaiseExceptionErrorHandler.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/event/EventHandler.java b/core-api/src/main/java/com/optimizely/ab/event/EventHandler.java index 97f7ebfcc..7df38fabb 100644 --- a/core-api/src/main/java/com/optimizely/ab/event/EventHandler.java +++ b/core-api/src/main/java/com/optimizely/ab/event/EventHandler.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/event/LogEvent.java b/core-api/src/main/java/com/optimizely/ab/event/LogEvent.java index f8e72fc0a..a353d9877 100644 --- a/core-api/src/main/java/com/optimizely/ab/event/LogEvent.java +++ b/core-api/src/main/java/com/optimizely/ab/event/LogEvent.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/event/NoopEventHandler.java b/core-api/src/main/java/com/optimizely/ab/event/NoopEventHandler.java index 723c898a8..e84ff4c58 100644 --- a/core-api/src/main/java/com/optimizely/ab/event/NoopEventHandler.java +++ b/core-api/src/main/java/com/optimizely/ab/event/NoopEventHandler.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/event/internal/BuildVersionInfo.java b/core-api/src/main/java/com/optimizely/ab/event/internal/BuildVersionInfo.java index 9d4778797..c86568fe8 100644 --- a/core-api/src/main/java/com/optimizely/ab/event/internal/BuildVersionInfo.java +++ b/core-api/src/main/java/com/optimizely/ab/event/internal/BuildVersionInfo.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/event/internal/EventBuilder.java b/core-api/src/main/java/com/optimizely/ab/event/internal/EventBuilder.java index 33bf72272..b2c4a39ef 100644 --- a/core-api/src/main/java/com/optimizely/ab/event/internal/EventBuilder.java +++ b/core-api/src/main/java/com/optimizely/ab/event/internal/EventBuilder.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,24 +25,16 @@ import javax.annotation.CheckForNull; import javax.annotation.Nonnull; +import java.util.Collections; import java.util.Map; public abstract class EventBuilder { - public LogEvent createImpressionEvent(@Nonnull ProjectConfig projectConfig, - @Nonnull Experiment activatedExperiment, - @Nonnull Variation variation, - @Nonnull String userId, - @Nonnull Map attributes) { - return createImpressionEvent(projectConfig, activatedExperiment, variation, userId, attributes, null); - } - public abstract LogEvent createImpressionEvent(@Nonnull ProjectConfig projectConfig, @Nonnull Experiment activatedExperiment, @Nonnull Variation variation, @Nonnull String userId, - @Nonnull Map attributes, - @CheckForNull String sessionId); + @Nonnull Map attributes); public LogEvent createConversionEvent(@Nonnull ProjectConfig projectConfig, @Nonnull Bucketer bucketer, @@ -50,18 +42,7 @@ public LogEvent createConversionEvent(@Nonnull ProjectConfig projectConfig, @Nonnull String eventId, @Nonnull String eventName, @Nonnull Map attributes) { - return createConversionEvent(projectConfig, bucketer, userId, eventId, eventName, attributes, null, null); - } - - public LogEvent createConversionEvent(@Nonnull ProjectConfig projectConfig, - @Nonnull Bucketer bucketer, - @Nonnull String userId, - @Nonnull String eventId, - @Nonnull String eventName, - @Nonnull Map attributes, - long eventValue) { - return createConversionEvent(projectConfig, bucketer, userId, eventId, eventName, attributes, (Long)eventValue, - null); + return createConversionEvent(projectConfig, bucketer, userId, eventId, eventName, attributes, Collections.emptyMap()); } public abstract LogEvent createConversionEvent(@Nonnull ProjectConfig projectConfig, @@ -70,6 +51,5 @@ public abstract LogEvent createConversionEvent(@Nonnull ProjectConfig projectCon @Nonnull String eventId, @Nonnull String eventName, @Nonnull Map attributes, - @CheckForNull Long eventValue, - @CheckForNull String sessionId); + @Nonnull Map eventTags); } diff --git a/core-api/src/main/java/com/optimizely/ab/event/internal/EventBuilderV1.java b/core-api/src/main/java/com/optimizely/ab/event/internal/EventBuilderV1.java index a1a4860b7..3aead7152 100644 --- a/core-api/src/main/java/com/optimizely/ab/event/internal/EventBuilderV1.java +++ b/core-api/src/main/java/com/optimizely/ab/event/internal/EventBuilderV1.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,6 +17,7 @@ package com.optimizely.ab.event.internal; import com.optimizely.ab.event.LogEvent; +import com.optimizely.ab.internal.EventTagUtils; import com.optimizely.ab.internal.ProjectValidationUtils; import com.optimizely.ab.bucketing.Bucketer; import com.optimizely.ab.config.Attribute; @@ -67,8 +68,7 @@ public LogEvent createImpressionEvent(@Nonnull ProjectConfig projectConfig, @Nonnull Experiment activatedExperiment, @Nonnull Variation variation, @Nonnull String userId, - @Nonnull Map attributes, - @CheckForNull String sessionId) { + @Nonnull Map attributes) { Map requestParams = new HashMap(); addCommonRequestParams(requestParams, projectConfig, userId, attributes); @@ -85,8 +85,7 @@ public LogEvent createConversionEvent(@Nonnull ProjectConfig projectConfig, @Nonnull String eventId, @Nonnull String eventName, @Nonnull Map attributes, - @CheckForNull Long eventValue, - @CheckForNull String sessionId) { + @Nonnull Map eventTags) { Map requestParams = new HashMap(); List addedExperiments = @@ -96,6 +95,7 @@ public LogEvent createConversionEvent(@Nonnull ProjectConfig projectConfig, return null; } + Long eventValue = EventTagUtils.getRevenueValue(eventTags); addCommonRequestParams(requestParams, projectConfig, userId, attributes); addConversionGoal(requestParams, projectConfig, eventId, eventName, eventValue); diff --git a/core-api/src/main/java/com/optimizely/ab/event/internal/EventBuilderV2.java b/core-api/src/main/java/com/optimizely/ab/event/internal/EventBuilderV2.java index 295dcf565..eb835d543 100644 --- a/core-api/src/main/java/com/optimizely/ab/event/internal/EventBuilderV2.java +++ b/core-api/src/main/java/com/optimizely/ab/event/internal/EventBuilderV2.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -32,6 +32,7 @@ import com.optimizely.ab.event.internal.payload.LayerState; import com.optimizely.ab.event.internal.serializer.DefaultJsonSerializer; import com.optimizely.ab.event.internal.serializer.Serializer; +import com.optimizely.ab.internal.EventTagUtils; import com.optimizely.ab.internal.ProjectValidationUtils; import org.slf4j.Logger; @@ -76,8 +77,7 @@ public LogEvent createImpressionEvent(@Nonnull ProjectConfig projectConfig, @Nonnull Experiment activatedExperiment, @Nonnull Variation variation, @Nonnull String userId, - @Nonnull Map attributes, - @CheckForNull String sessionId) { + @Nonnull Map attributes) { Impression impressionPayload = new Impression(); impressionPayload.setVisitorId(userId); @@ -93,12 +93,11 @@ public LogEvent createImpressionEvent(@Nonnull ProjectConfig projectConfig, impressionPayload.setLayerId(activatedExperiment.getLayerId()); impressionPayload.setAccountId(projectConfig.getAccountId()); - impressionPayload.setUserFeatures(createFeatures(attributes, projectConfig)); + impressionPayload.setUserFeatures(createUserFeatures(attributes, projectConfig)); impressionPayload.setClientEngine(clientEngine); impressionPayload.setClientVersion(clientVersion); impressionPayload.setAnonymizeIP(projectConfig.getAnonymizeIP()); impressionPayload.setRevision(projectConfig.getRevision()); - impressionPayload.setSessionId(sessionId); String payload = this.serializer.serialize(impressionPayload); return new LogEvent(RequestMethod.POST, IMPRESSION_ENDPOINT, Collections.emptyMap(), payload); @@ -110,15 +109,14 @@ public LogEvent createConversionEvent(@Nonnull ProjectConfig projectConfig, @Nonnull String eventId, @Nonnull String eventName, @Nonnull Map attributes, - @CheckForNull Long eventValue, - @CheckForNull String sessionId) { + @Nonnull Map eventTags) { Conversion conversionPayload = new Conversion(); conversionPayload.setVisitorId(userId); conversionPayload.setTimestamp(System.currentTimeMillis()); conversionPayload.setProjectId(projectConfig.getProjectId()); conversionPayload.setAccountId(projectConfig.getAccountId()); - conversionPayload.setUserFeatures(createFeatures(attributes, projectConfig)); + conversionPayload.setUserFeatures(createUserFeatures(attributes, projectConfig)); List layerStates = createLayerStates(projectConfig, bucketer, userId, eventName, attributes); if (layerStates.isEmpty()) { @@ -129,6 +127,7 @@ public LogEvent createConversionEvent(@Nonnull ProjectConfig projectConfig, conversionPayload.setEventEntityId(eventId); conversionPayload.setEventName(eventName); + Long eventValue = EventTagUtils.getRevenueValue(eventTags); if (eventValue != null) { conversionPayload.setEventMetrics( Collections.singletonList(new EventMetric(EventMetric.REVENUE_METRIC_TYPE, eventValue))); @@ -142,8 +141,7 @@ public LogEvent createConversionEvent(@Nonnull ProjectConfig projectConfig, conversionPayload.setClientEngine(clientEngine); conversionPayload.setClientVersion(clientVersion); conversionPayload.setRevision(projectConfig.getRevision()); - conversionPayload.setSessionId(sessionId); - + conversionPayload.setEventFeatures(createEventFeatures(eventTags)); String payload = this.serializer.serialize(conversionPayload); return new LogEvent(RequestMethod.POST, CONVERSION_ENDPOINT, Collections.emptyMap(), payload); @@ -155,7 +153,7 @@ public LogEvent createConversionEvent(@Nonnull ProjectConfig projectConfig, * @param attributes the {@code {attributeKey -> value}} mapping * @param projectConfig the current project config */ - private List createFeatures(Map attributes, ProjectConfig projectConfig) { + private List createUserFeatures(Map attributes, ProjectConfig projectConfig) { Map attributeKeyMapping = projectConfig.getAttributeKeyMapping(); List features = new ArrayList(); @@ -175,6 +173,21 @@ private List createFeatures(Map attributes, ProjectConf return features; } + /** + * Helper method to generate {@link Feature} objects from the given {@code {eventTagKey-> value}} mapping. + * + * @param eventTags the {@code {eventTagKey -> value}} mapping + */ + private List createEventFeatures(Map eventTags) { + List features = new ArrayList(); + + for (Map.Entry eventTagEntry : eventTags.entrySet()) { + String eventTagKey = eventTagEntry.getKey(); + features.add(new Feature("", eventTagKey, Feature.EVENT_FEATURE_TYPE, eventTagEntry.getValue(), false)); + } + return features; + } + /** * Helper method to create {@link LayerState} objects for all experiments mapped to an event. *

diff --git a/core-api/src/main/java/com/optimizely/ab/event/internal/payload/Conversion.java b/core-api/src/main/java/com/optimizely/ab/event/internal/payload/Conversion.java index f2a02a7b1..9c54389bc 100644 --- a/core-api/src/main/java/com/optimizely/ab/event/internal/payload/Conversion.java +++ b/core-api/src/main/java/com/optimizely/ab/event/internal/payload/Conversion.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/event/internal/payload/Decision.java b/core-api/src/main/java/com/optimizely/ab/event/internal/payload/Decision.java index 93314a890..d641552a1 100644 --- a/core-api/src/main/java/com/optimizely/ab/event/internal/payload/Decision.java +++ b/core-api/src/main/java/com/optimizely/ab/event/internal/payload/Decision.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/event/internal/payload/Event.java b/core-api/src/main/java/com/optimizely/ab/event/internal/payload/Event.java index 9237d5b96..974a72a4c 100644 --- a/core-api/src/main/java/com/optimizely/ab/event/internal/payload/Event.java +++ b/core-api/src/main/java/com/optimizely/ab/event/internal/payload/Event.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/event/internal/payload/EventMetric.java b/core-api/src/main/java/com/optimizely/ab/event/internal/payload/EventMetric.java index 34ad16cf6..5303871c9 100644 --- a/core-api/src/main/java/com/optimizely/ab/event/internal/payload/EventMetric.java +++ b/core-api/src/main/java/com/optimizely/ab/event/internal/payload/EventMetric.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/event/internal/payload/Feature.java b/core-api/src/main/java/com/optimizely/ab/event/internal/payload/Feature.java index 8f54be74e..22df21df9 100644 --- a/core-api/src/main/java/com/optimizely/ab/event/internal/payload/Feature.java +++ b/core-api/src/main/java/com/optimizely/ab/event/internal/payload/Feature.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,16 +19,17 @@ public class Feature { public static final String CUSTOM_ATTRIBUTE_FEATURE_TYPE = "custom"; + public static final String EVENT_FEATURE_TYPE = "custom"; private String id; private String name; private String type; - private String value; + private Object value; private boolean shouldIndex; public Feature() { } - public Feature(String id, String name, String type, String value, boolean shouldIndex) { + public Feature(String id, String name, String type, Object value, boolean shouldIndex) { this.id = id; this.name = name; this.type = type; @@ -60,7 +61,7 @@ public void setType(String type) { this.type = type; } - public String getValue() { + public Object getValue() { return value; } diff --git a/core-api/src/main/java/com/optimizely/ab/event/internal/payload/Impression.java b/core-api/src/main/java/com/optimizely/ab/event/internal/payload/Impression.java index 771c1213c..33878a09f 100644 --- a/core-api/src/main/java/com/optimizely/ab/event/internal/payload/Impression.java +++ b/core-api/src/main/java/com/optimizely/ab/event/internal/payload/Impression.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/event/internal/payload/LayerState.java b/core-api/src/main/java/com/optimizely/ab/event/internal/payload/LayerState.java index 02915ffdf..589197be7 100644 --- a/core-api/src/main/java/com/optimizely/ab/event/internal/payload/LayerState.java +++ b/core-api/src/main/java/com/optimizely/ab/event/internal/payload/LayerState.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/event/internal/serializer/DefaultJsonSerializer.java b/core-api/src/main/java/com/optimizely/ab/event/internal/serializer/DefaultJsonSerializer.java index e027f6784..717ac9e0b 100644 --- a/core-api/src/main/java/com/optimizely/ab/event/internal/serializer/DefaultJsonSerializer.java +++ b/core-api/src/main/java/com/optimizely/ab/event/internal/serializer/DefaultJsonSerializer.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/event/internal/serializer/GsonSerializer.java b/core-api/src/main/java/com/optimizely/ab/event/internal/serializer/GsonSerializer.java index 5d06715fe..a5a7aafba 100644 --- a/core-api/src/main/java/com/optimizely/ab/event/internal/serializer/GsonSerializer.java +++ b/core-api/src/main/java/com/optimizely/ab/event/internal/serializer/GsonSerializer.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/event/internal/serializer/JacksonSerializer.java b/core-api/src/main/java/com/optimizely/ab/event/internal/serializer/JacksonSerializer.java index 107aa47ff..afc316d34 100644 --- a/core-api/src/main/java/com/optimizely/ab/event/internal/serializer/JacksonSerializer.java +++ b/core-api/src/main/java/com/optimizely/ab/event/internal/serializer/JacksonSerializer.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/event/internal/serializer/JsonSerializer.java b/core-api/src/main/java/com/optimizely/ab/event/internal/serializer/JsonSerializer.java index b8d329735..eb1fa71e9 100644 --- a/core-api/src/main/java/com/optimizely/ab/event/internal/serializer/JsonSerializer.java +++ b/core-api/src/main/java/com/optimizely/ab/event/internal/serializer/JsonSerializer.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/event/internal/serializer/JsonSimpleSerializer.java b/core-api/src/main/java/com/optimizely/ab/event/internal/serializer/JsonSimpleSerializer.java index 625754200..549fc230e 100644 --- a/core-api/src/main/java/com/optimizely/ab/event/internal/serializer/JsonSimpleSerializer.java +++ b/core-api/src/main/java/com/optimizely/ab/event/internal/serializer/JsonSimpleSerializer.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/event/internal/serializer/SerializationException.java b/core-api/src/main/java/com/optimizely/ab/event/internal/serializer/SerializationException.java index de1110ff1..798d1a552 100644 --- a/core-api/src/main/java/com/optimizely/ab/event/internal/serializer/SerializationException.java +++ b/core-api/src/main/java/com/optimizely/ab/event/internal/serializer/SerializationException.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/event/internal/serializer/Serializer.java b/core-api/src/main/java/com/optimizely/ab/event/internal/serializer/Serializer.java index 24d703c45..01bd4c123 100644 --- a/core-api/src/main/java/com/optimizely/ab/event/internal/serializer/Serializer.java +++ b/core-api/src/main/java/com/optimizely/ab/event/internal/serializer/Serializer.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/internal/EventTagUtils.java b/core-api/src/main/java/com/optimizely/ab/internal/EventTagUtils.java new file mode 100644 index 000000000..42dacfc5e --- /dev/null +++ b/core-api/src/main/java/com/optimizely/ab/internal/EventTagUtils.java @@ -0,0 +1,50 @@ +/** + * + * Copyright 2016-2017, Optimizely 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.internal; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.annotation.Nonnull; +import java.util.Map; + +public final class EventTagUtils { + + private static final Logger logger = LoggerFactory.getLogger(EventTagUtils.class); + + /** + * Grab the revenue value from the event tags. "revenue" is a reserved keyword. + * @param eventTags + * @return Long + */ + public static Long getRevenueValue(@Nonnull Map eventTags) { + Long eventValue = null; + if (eventTags.containsKey(ReservedEventKey.REVENUE.toString())) { + Object rawValue = eventTags.get(ReservedEventKey.REVENUE.toString()); + if (Long.class.isInstance(rawValue)) { + eventValue = (Long)rawValue; + logger.info("Parsed revenue value \"{}\" from event tags.", eventValue); + } else if (Integer.class.isInstance(rawValue)) { + eventValue = ((Integer)rawValue).longValue(); + logger.info("Parsed revenue value \"{}\" from event tags.", eventValue); + } else { + logger.warn("Failed to parse revenue value \"{}\" from event tags.", rawValue); + } + } + return eventValue; + } +} diff --git a/core-api/src/main/java/com/optimizely/ab/internal/ProjectValidationUtils.java b/core-api/src/main/java/com/optimizely/ab/internal/ProjectValidationUtils.java index 2ea00ea79..da283155d 100644 --- a/core-api/src/main/java/com/optimizely/ab/internal/ProjectValidationUtils.java +++ b/core-api/src/main/java/com/optimizely/ab/internal/ProjectValidationUtils.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/internal/ReservedEventKey.java b/core-api/src/main/java/com/optimizely/ab/internal/ReservedEventKey.java new file mode 100644 index 000000000..ecc30f5b6 --- /dev/null +++ b/core-api/src/main/java/com/optimizely/ab/internal/ReservedEventKey.java @@ -0,0 +1,32 @@ +/** + * + * Copyright 2016-2017, Optimizely 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.internal; + +public enum ReservedEventKey { + REVENUE("revenue"); + + private final String key; + + ReservedEventKey(String key) { + this.key = key; + } + + @Override + public String toString() { + return key; + } +} diff --git a/core-api/src/main/java/com/optimizely/ab/notification/NotificationBroadcaster.java b/core-api/src/main/java/com/optimizely/ab/notification/NotificationBroadcaster.java index d9df413c0..bb77468df 100644 --- a/core-api/src/main/java/com/optimizely/ab/notification/NotificationBroadcaster.java +++ b/core-api/src/main/java/com/optimizely/ab/notification/NotificationBroadcaster.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/notification/NotificationListener.java b/core-api/src/main/java/com/optimizely/ab/notification/NotificationListener.java index a7c12820a..2fe6e6bc1 100644 --- a/core-api/src/main/java/com/optimizely/ab/notification/NotificationListener.java +++ b/core-api/src/main/java/com/optimizely/ab/notification/NotificationListener.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/test/java/com/optimizely/ab/OptimizelyBuilderTest.java b/core-api/src/test/java/com/optimizely/ab/OptimizelyBuilderTest.java index 13557bc76..b9958a194 100644 --- a/core-api/src/test/java/com/optimizely/ab/OptimizelyBuilderTest.java +++ b/core-api/src/test/java/com/optimizely/ab/OptimizelyBuilderTest.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/test/java/com/optimizely/ab/OptimizelyTestV1.java b/core-api/src/test/java/com/optimizely/ab/OptimizelyTestV1.java index 55af6086d..47fa1b966 100644 --- a/core-api/src/test/java/com/optimizely/ab/OptimizelyTestV1.java +++ b/core-api/src/test/java/com/optimizely/ab/OptimizelyTestV1.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -35,6 +35,7 @@ import com.optimizely.ab.event.internal.EventBuilderV1; import com.optimizely.ab.internal.LogbackVerifier; import com.optimizely.ab.internal.ProjectValidationUtils; +import com.optimizely.ab.internal.ReservedEventKey; import org.junit.Rule; import org.junit.Test; @@ -122,7 +123,7 @@ public void activateEndToEnd() throws Exception { testParams.put("test", "params"); LogEvent logEventToDispatch = new LogEvent(RequestMethod.GET, "test_url", testParams, ""); when(mockEventBuilder.createImpressionEvent(projectConfig, activatedExperiment, bucketedVariation, "userId", - testUserAttributes, null)) + testUserAttributes)) .thenReturn(logEventToDispatch); when(mockBucketer.bucket(activatedExperiment, "userId")) @@ -251,7 +252,7 @@ public void activateWithExperimentKey() throws Exception { testParams.put("test", "params"); LogEvent logEventToDispatch = new LogEvent(RequestMethod.GET, "test_url", testParams, ""); when(mockEventBuilder.createImpressionEvent(eq(projectConfig), eq(activatedExperiment), eq(bucketedVariation), - eq("userId"), eq(testUserAttributes), isNull(String.class))) + eq("userId"), eq(testUserAttributes))) .thenReturn(logEventToDispatch); when(mockBucketer.bucket(activatedExperiment, "userId")) @@ -340,8 +341,7 @@ public void activateWithAttributes() throws Exception { testParams.put("test", "params"); LogEvent logEventToDispatch = new LogEvent(RequestMethod.GET, "test_url", testParams, ""); when(mockEventBuilder.createImpressionEvent(eq(projectConfig), eq(activatedExperiment), eq(bucketedVariation), - eq("userId"), anyMapOf(String.class, String.class), - isNull(String.class))) + eq("userId"), anyMapOf(String.class, String.class))) .thenReturn(logEventToDispatch); when(mockBucketer.bucket(activatedExperiment, "userId")) @@ -361,8 +361,7 @@ public void activateWithAttributes() throws Exception { eq(activatedExperiment), eq(bucketedVariation), eq("userId"), - attributeCaptor.capture(), - isNull(String.class)); + attributeCaptor.capture()); Map actualValue = attributeCaptor.getValue(); assertThat(actualValue, hasEntry(attribute.getKey(), "attributeValue")); @@ -403,8 +402,7 @@ public void activateWithUnknownAttribute() throws Exception { testParams.put("test", "params"); LogEvent logEventToDispatch = new LogEvent(RequestMethod.GET, "test_url", testParams, ""); when(mockEventBuilder.createImpressionEvent(eq(projectConfig), eq(activatedExperiment), eq(bucketedVariation), - eq("userId"), anyMapOf(String.class, String.class), - isNull(String.class))) + eq("userId"), anyMapOf(String.class, String.class))) .thenReturn(logEventToDispatch); when(mockBucketer.bucket(activatedExperiment, "userId")) @@ -426,8 +424,7 @@ public void activateWithUnknownAttribute() throws Exception { // verify that the event builder was called with the expected attributes verify(mockEventBuilder).createImpressionEvent(eq(projectConfig), eq(activatedExperiment), - eq(bucketedVariation), eq("userId"), attributeCaptor.capture(), - isNull(String.class)); + eq(bucketedVariation), eq("userId"), attributeCaptor.capture()); Map actualValue = attributeCaptor.getValue(); assertThat(actualValue, not(hasKey("unknownAttribute"))); @@ -794,8 +791,8 @@ public void trackEventWithAttributes() throws Exception { LogEvent logEventToDispatch = new LogEvent(RequestMethod.GET, "test_url", testParams, ""); when(mockEventBuilder.createConversionEvent(eq(projectConfig), eq(mockBucketer), eq("userId"), eq(eventType.getId()), eq(eventType.getKey()), - anyMapOf(String.class, String.class), isNull(Long.class), - isNull(String.class))) + anyMapOf(String.class, String.class), + anyMapOf(String.class, Object.class))) .thenReturn(logEventToDispatch); logbackVerifier.expectMessage(Level.INFO, "Tracking event \"clicked_cart\" for user \"userId\"."); @@ -811,8 +808,8 @@ public void trackEventWithAttributes() throws Exception { // verify that the event builder was called with the expected attributes verify(mockEventBuilder).createConversionEvent(eq(projectConfig), eq(mockBucketer), eq("userId"), eq(eventType.getId()), eq(eventType.getKey()), - attributeCaptor.capture(), isNull(Long.class), - isNull(String.class)); + attributeCaptor.capture(), + eq(Collections.emptyMap())); Map actualValue = attributeCaptor.getValue(); assertThat(actualValue, hasEntry(attribute.getKey(), "attributeValue")); @@ -848,8 +845,8 @@ public void trackEventWithUnknownAttribute() throws Exception { LogEvent logEventToDispatch = new LogEvent(RequestMethod.GET, "test_url", testParams, ""); when(mockEventBuilder.createConversionEvent(eq(projectConfig), eq(mockBucketer), eq("userId"), eq(eventType.getId()), eq(eventType.getKey()), - anyMapOf(String.class, String.class), isNull(Long.class), - isNull(String.class))) + anyMapOf(String.class, String.class), + anyMapOf(String.class, Object.class))) .thenReturn(logEventToDispatch); logbackVerifier.expectMessage(Level.INFO, "Tracking event \"clicked_cart\" for user \"userId\"."); @@ -866,8 +863,8 @@ public void trackEventWithUnknownAttribute() throws Exception { // verify that the event builder was called with the expected attributes verify(mockEventBuilder).createConversionEvent(eq(projectConfig), eq(mockBucketer), eq("userId"), eq(eventType.getId()), eq(eventType.getKey()), - attributeCaptor.capture(), isNull(Long.class), - isNull(String.class)); + attributeCaptor.capture(), + eq(Collections.emptyMap())); Map actualValue = attributeCaptor.getValue(); assertThat(actualValue, not(hasKey("unknownAttribute"))); @@ -900,23 +897,23 @@ public void trackEventWithRevenue() throws Exception { LogEvent logEventToDispatch = new LogEvent(RequestMethod.GET, "test_url", testParams, ""); when(mockEventBuilder.createConversionEvent(eq(projectConfig), eq(mockBucketer), eq("userId"), eq(eventType.getId()), eq(eventType.getKey()), - eq(Collections.emptyMap()), eq(revenue), - isNull(String.class))) + eq(Collections.emptyMap()), + eq(Collections.singletonMap(ReservedEventKey.REVENUE.toString(), revenue)))) .thenReturn(logEventToDispatch); // call track optimizely.track(eventType.getKey(), "userId", revenue); - // setup the revenue captor (so we can verify its content) - ArgumentCaptor revenueCaptor = ArgumentCaptor.forClass(Long.class); + // setup the event tag map captor (capture the revenue value, which is a reserved keyword) + ArgumentCaptor eventTagCaptor = ArgumentCaptor.forClass(Map.class); // verify that the event builder was called with the expected revenue verify(mockEventBuilder).createConversionEvent(eq(projectConfig), eq(mockBucketer), eq("userId"), eq(eventType.getId()), eq(eventType.getKey()), eq(Collections.emptyMap()), - revenueCaptor.capture(), isNull(String.class)); + eventTagCaptor.capture()); - Long actualValue = revenueCaptor.getValue(); + Long actualValue = (Long)eventTagCaptor.getValue().get(ReservedEventKey.REVENUE.toString()); assertThat(actualValue, is(revenue)); verify(mockEventHandler).dispatchEvent(logEventToDispatch); diff --git a/core-api/src/test/java/com/optimizely/ab/OptimizelyTestV2.java b/core-api/src/test/java/com/optimizely/ab/OptimizelyTestV2.java index e77d186a7..fedbfb88e 100644 --- a/core-api/src/test/java/com/optimizely/ab/OptimizelyTestV2.java +++ b/core-api/src/test/java/com/optimizely/ab/OptimizelyTestV2.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -35,6 +35,7 @@ import com.optimizely.ab.event.internal.EventBuilderV2; import com.optimizely.ab.internal.LogbackVerifier; import com.optimizely.ab.internal.ProjectValidationUtils; +import com.optimizely.ab.internal.ReservedEventKey; import org.junit.BeforeClass; import org.junit.Rule; @@ -46,9 +47,9 @@ import org.mockito.junit.MockitoRule; import java.util.Collections; -import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.HashMap; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; @@ -134,7 +135,7 @@ public void activateEndToEnd() throws Exception { testParams.put("test", "params"); LogEvent logEventToDispatch = new LogEvent(RequestMethod.GET, "test_url", testParams, ""); when(mockEventBuilder.createImpressionEvent(validProjectConfig, activatedExperiment, bucketedVariation, "userId", - testUserAttributes, null)) + testUserAttributes)) .thenReturn(logEventToDispatch); when(mockBucketer.bucket(activatedExperiment, "userId")) @@ -255,7 +256,7 @@ public void activateWithExperimentKey() throws Exception { testParams.put("test", "params"); LogEvent logEventToDispatch = new LogEvent(RequestMethod.GET, "test_url", testParams, ""); when(mockEventBuilder.createImpressionEvent(eq(validProjectConfig), eq(activatedExperiment), eq(bucketedVariation), - eq("userId"), eq(testUserAttributes), isNull(String.class))) + eq("userId"), eq(testUserAttributes))) .thenReturn(logEventToDispatch); when(mockBucketer.bucket(activatedExperiment, "userId")) @@ -339,8 +340,7 @@ public void activateWithAttributes() throws Exception { testParams.put("test", "params"); LogEvent logEventToDispatch = new LogEvent(RequestMethod.GET, "test_url", testParams, ""); when(mockEventBuilder.createImpressionEvent(eq(validProjectConfig), eq(activatedExperiment), eq(bucketedVariation), - eq("userId"), anyMapOf(String.class, String.class), - isNull(String.class))) + eq("userId"), anyMapOf(String.class, String.class))) .thenReturn(logEventToDispatch); when(mockBucketer.bucket(activatedExperiment, "userId")) @@ -357,8 +357,7 @@ public void activateWithAttributes() throws Exception { // setup the attribute map captor (so we can verify its content) ArgumentCaptor attributeCaptor = ArgumentCaptor.forClass(Map.class); verify(mockEventBuilder).createImpressionEvent(eq(validProjectConfig), eq(activatedExperiment), - eq(bucketedVariation), eq("userId"), attributeCaptor.capture(), - isNull(String.class)); + eq(bucketedVariation), eq("userId"), attributeCaptor.capture()); Map actualValue = attributeCaptor.getValue(); assertThat(actualValue, hasEntry(attribute.getKey(), "attributeValue")); @@ -397,8 +396,7 @@ public void activateWithUnknownAttribute() throws Exception { testParams.put("test", "params"); LogEvent logEventToDispatch = new LogEvent(RequestMethod.GET, "test_url", testParams, ""); when(mockEventBuilder.createImpressionEvent(eq(validProjectConfig), eq(activatedExperiment), eq(bucketedVariation), - eq("userId"), anyMapOf(String.class, String.class), - isNull(String.class))) + eq("userId"), anyMapOf(String.class, String.class))) .thenReturn(logEventToDispatch); when(mockBucketer.bucket(activatedExperiment, "userId")) @@ -420,8 +418,7 @@ public void activateWithUnknownAttribute() throws Exception { // verify that the event builder was called with the expected attributes verify(mockEventBuilder).createImpressionEvent(eq(validProjectConfig), eq(activatedExperiment), - eq(bucketedVariation), eq("userId"), attributeCaptor.capture(), - isNull(String.class)); + eq(bucketedVariation), eq("userId"), attributeCaptor.capture()); Map actualValue = attributeCaptor.getValue(); assertThat(actualValue, not(hasKey("unknownAttribute"))); @@ -457,8 +454,7 @@ public void activateWithNullAttributes() throws Exception { testParams.put("test", "params"); LogEvent logEventToDispatch = new LogEvent(RequestMethod.GET, "test_url", testParams, ""); when(mockEventBuilder.createImpressionEvent(eq(projectConfig), eq(activatedExperiment), eq(bucketedVariation), - eq("userId"), eq(Collections.emptyMap()), - isNull(String.class))) + eq("userId"), eq(Collections.emptyMap()))) .thenReturn(logEventToDispatch); when(mockBucketer.bucket(activatedExperiment, "userId")) @@ -477,8 +473,7 @@ public void activateWithNullAttributes() throws Exception { // setup the attribute map captor (so we can verify its content) ArgumentCaptor attributeCaptor = ArgumentCaptor.forClass(Map.class); verify(mockEventBuilder).createImpressionEvent(eq(projectConfig), eq(activatedExperiment), - eq(bucketedVariation), eq("userId"), attributeCaptor.capture(), - isNull(String.class)); + eq(bucketedVariation), eq("userId"), attributeCaptor.capture()); Map actualValue = attributeCaptor.getValue(); assertThat(actualValue, is(Collections.emptyMap())); @@ -512,8 +507,7 @@ public void activateWithNullAttributeValues() throws Exception { testParams.put("test", "params"); LogEvent logEventToDispatch = new LogEvent(RequestMethod.GET, "test_url", testParams, ""); when(mockEventBuilder.createImpressionEvent(eq(projectConfig), eq(activatedExperiment), eq(bucketedVariation), - eq("userId"), anyMapOf(String.class, String.class), - isNull(String.class))) + eq("userId"), anyMapOf(String.class, String.class))) .thenReturn(logEventToDispatch); when(mockBucketer.bucket(activatedExperiment, "userId")) @@ -531,8 +525,7 @@ public void activateWithNullAttributeValues() throws Exception { // setup the attribute map captor (so we can verify its content) ArgumentCaptor attributeCaptor = ArgumentCaptor.forClass(Map.class); verify(mockEventBuilder).createImpressionEvent(eq(projectConfig), eq(activatedExperiment), - eq(bucketedVariation), eq("userId"), attributeCaptor.capture(), - isNull(String.class)); + eq(bucketedVariation), eq("userId"), attributeCaptor.capture()); Map actualValue = attributeCaptor.getValue(); assertThat(actualValue, hasEntry(attribute.getKey(), null)); @@ -786,39 +779,6 @@ public void activateLaunchedExperimentDoesNotDispatchEvent() throws Exception { verify(mockEventHandler, never()).dispatchEvent(any(LogEvent.class)); } - /** - * Verify that {@link Optimizely#activate(String, String, String)} passes the session ID to - * {@link EventBuilder#createImpressionEvent(ProjectConfig, Experiment, Variation, String, Map, String)} - */ - @Test - public void activateWithSessionId() throws Exception { - Experiment experiment = noAudienceProjectConfig.getExperiments().get(0); - - EventBuilder mockEventBuilder = mock(EventBuilder.class); - - Map testParams = new HashMap(); - testParams.put("test", "params"); - LogEvent logEventToDispatch = new LogEvent(RequestMethod.GET, "test_url", testParams, ""); - - when(mockEventBuilder.createImpressionEvent(eq(noAudienceProjectConfig), any(Experiment.class), any(Variation.class), - eq("userId"), eq(Collections.emptyMap()), - eq("test_session_id"))) - .thenReturn(logEventToDispatch); - - Optimizely optimizely = Optimizely.builder(noAudienceDatafile, mockEventHandler) - .withConfig(noAudienceProjectConfig) - .withEventBuilder(mockEventBuilder) - .build(); - - optimizely.activate(experiment.getKey(), "userId", "test_session_id"); - - // verify that the event builder was called with the expected attributes - verify(mockEventBuilder).createImpressionEvent(eq(noAudienceProjectConfig), any(Experiment.class), - any(Variation.class), eq("userId"), - eq(Collections.emptyMap()), - eq("test_session_id")); - } - //======== track tests ========// /** @@ -931,8 +891,7 @@ public void trackEventWithAttributes() throws Exception { LogEvent logEventToDispatch = new LogEvent(RequestMethod.GET, "test_url", testParams, ""); when(mockEventBuilder.createConversionEvent(eq(validProjectConfig), eq(mockBucketer), eq("userId"), eq(eventType.getId()), eq(eventType.getKey()), - anyMapOf(String.class, String.class), isNull(Long.class), - isNull(String.class))) + anyMapOf(String.class, String.class), eq(Collections.emptyMap()))) .thenReturn(logEventToDispatch); logbackVerifier.expectMessage(Level.INFO, "Tracking event \"clicked_cart\" for user \"userId\"."); @@ -948,8 +907,7 @@ public void trackEventWithAttributes() throws Exception { // verify that the event builder was called with the expected attributes verify(mockEventBuilder).createConversionEvent(eq(validProjectConfig), eq(mockBucketer), eq("userId"), eq(eventType.getId()), eq(eventType.getKey()), - attributeCaptor.capture(), isNull(Long.class), - isNull(String.class)); + attributeCaptor.capture(), eq(Collections.emptyMap())); Map actualValue = attributeCaptor.getValue(); assertThat(actualValue, hasEntry(attribute.getKey(), "attributeValue")); @@ -984,8 +942,7 @@ public void trackEventWithNullAttributes() throws Exception { LogEvent logEventToDispatch = new LogEvent(RequestMethod.GET, "test_url", testParams, ""); when(mockEventBuilder.createConversionEvent(eq(projectConfig), eq(mockBucketer), eq("userId"), eq(eventType.getId()), eq(eventType.getKey()), - eq(Collections.emptyMap()), isNull(Long.class), - isNull(String.class))) + eq(Collections.emptyMap()), eq(Collections.emptyMap()))) .thenReturn(logEventToDispatch); logbackVerifier.expectMessage(Level.INFO, "Tracking event \"clicked_cart\" for user \"userId\"."); @@ -1004,8 +961,7 @@ public void trackEventWithNullAttributes() throws Exception { // verify that the event builder was called with the expected attributes verify(mockEventBuilder).createConversionEvent(eq(projectConfig), eq(mockBucketer), eq("userId"), eq(eventType.getId()), eq(eventType.getKey()), - attributeCaptor.capture(), isNull(Long.class), - isNull(String.class)); + attributeCaptor.capture(), eq(Collections.emptyMap())); Map actualValue = attributeCaptor.getValue(); assertThat(actualValue, is(Collections.emptyMap())); @@ -1037,8 +993,7 @@ public void trackEventWithNullAttributeValues() throws Exception { LogEvent logEventToDispatch = new LogEvent(RequestMethod.GET, "test_url", testParams, ""); when(mockEventBuilder.createConversionEvent(eq(projectConfig), eq(mockBucketer), eq("userId"), eq(eventType.getId()), eq(eventType.getKey()), - anyMapOf(String.class, String.class), isNull(Long.class), - isNull(String.class))) + anyMapOf(String.class, String.class), eq(Collections.emptyMap()))) .thenReturn(logEventToDispatch); logbackVerifier.expectMessage(Level.INFO, "Tracking event \"clicked_cart\" for user \"userId\"."); @@ -1056,8 +1011,7 @@ public void trackEventWithNullAttributeValues() throws Exception { // verify that the event builder was called with the expected attributes verify(mockEventBuilder).createConversionEvent(eq(projectConfig), eq(mockBucketer), eq("userId"), eq(eventType.getId()), eq(eventType.getKey()), - attributeCaptor.capture(), isNull(Long.class), - isNull(String.class)); + attributeCaptor.capture(), eq(Collections.emptyMap())); verify(mockEventHandler).dispatchEvent(logEventToDispatch); } @@ -1088,8 +1042,7 @@ public void trackEventWithUnknownAttribute() throws Exception { LogEvent logEventToDispatch = new LogEvent(RequestMethod.GET, "test_url", testParams, ""); when(mockEventBuilder.createConversionEvent(eq(validProjectConfig), eq(mockBucketer), eq("userId"), eq(eventType.getId()), eq(eventType.getKey()), - anyMapOf(String.class, String.class), isNull(Long.class), - isNull(String.class))) + anyMapOf(String.class, String.class), eq(Collections.emptyMap()))) .thenReturn(logEventToDispatch); logbackVerifier.expectMessage(Level.INFO, "Tracking event \"clicked_cart\" for user \"userId\"."); @@ -1106,8 +1059,7 @@ public void trackEventWithUnknownAttribute() throws Exception { // verify that the event builder was called with the expected attributes verify(mockEventBuilder).createConversionEvent(eq(validProjectConfig), eq(mockBucketer), eq("userId"), eq(eventType.getId()), eq(eventType.getKey()), - attributeCaptor.capture(), isNull(Long.class), - isNull(String.class)); + attributeCaptor.capture(), eq(Collections.emptyMap())); Map actualValue = attributeCaptor.getValue(); assertThat(actualValue, not(hasKey("unknownAttribute"))); @@ -1116,7 +1068,7 @@ public void trackEventWithUnknownAttribute() throws Exception { } /** - * Verify that {@link Optimizely#track(String, String)} passes through revenue. + * Verify that {@link Optimizely#track(String, String, long)} passes through revenue. */ @Test public void trackEventWithRevenue() throws Exception { @@ -1135,31 +1087,136 @@ public void trackEventWithRevenue() throws Exception { Map testParams = new HashMap(); testParams.put("test", "params"); + Map eventTags = new HashMap(); + eventTags.put(ReservedEventKey.REVENUE.toString(), revenue); LogEvent logEventToDispatch = new LogEvent(RequestMethod.GET, "test_url", testParams, ""); when(mockEventBuilder.createConversionEvent(eq(validProjectConfig), eq(mockBucketer), eq("userId"), eq(eventType.getId()), eq(eventType.getKey()), - eq(Collections.emptyMap()), eq(revenue), - isNull(String.class))) + eq(Collections.emptyMap()), eq(eventTags))) .thenReturn(logEventToDispatch); // call track optimizely.track(eventType.getKey(), "userId", revenue); - // setup the revenue captor (so we can verify its content) - ArgumentCaptor revenueCaptor = ArgumentCaptor.forClass(Long.class); + // setup the event tag map captor (so we can verify its content) + ArgumentCaptor eventTagCaptor = ArgumentCaptor.forClass(Map.class); // verify that the event builder was called with the expected revenue verify(mockEventBuilder).createConversionEvent(eq(validProjectConfig), eq(mockBucketer), eq("userId"), eq(eventType.getId()), eq(eventType.getKey()), eq(Collections.emptyMap()), - revenueCaptor.capture(), isNull(String.class)); + eventTagCaptor.capture()); - Long actualValue = revenueCaptor.getValue(); + Long actualValue = (Long)eventTagCaptor.getValue().get(ReservedEventKey.REVENUE.toString()); assertThat(actualValue, is(revenue)); verify(mockEventHandler).dispatchEvent(logEventToDispatch); } + /** + * Verify that {@link Optimizely#track(String, String, Map, Map)} passes event features to + * @{link EventBuilder#createConversionEvent(ProjectConfig, Bucketer, String, String, String, Map, Map)} + */ + @Test + public void trackEventWithEventTags() throws Exception { + String datafile = validConfigJsonV2(); + ProjectConfig projectConfig = validProjectConfigV2(); + EventType eventType = projectConfig.getEventTypes().get(0); + + // setup a mock event builder to return expected conversion params + EventBuilder mockEventBuilder = mock(EventBuilder.class); + + Optimizely optimizely = Optimizely.builder(datafile, mockEventHandler) + .withBucketing(mockBucketer) + .withEventBuilder(mockEventBuilder) + .withConfig(projectConfig) + .withErrorHandler(mockErrorHandler) + .build(); + + Map testParams = new HashMap(); + testParams.put("test", "params"); + LogEvent logEventToDispatch = new LogEvent(RequestMethod.GET, "test_url", testParams, ""); + when(mockEventBuilder.createConversionEvent(eq(projectConfig), eq(mockBucketer), eq("userId"), + eq(eventType.getId()), eq(eventType.getKey()), + anyMapOf(String.class, String.class), anyMapOf(String.class, Object.class))) + .thenReturn(logEventToDispatch); + + logbackVerifier.expectMessage(Level.INFO, "Tracking event \"clicked_cart\" for user \"userId\"."); + logbackVerifier.expectMessage(Level.DEBUG, "Dispatching conversion event to URL test_url with params " + + testParams + " and payload \"\""); + + Map eventTags = new HashMap(); + eventTags.put("int_param", 123); + eventTags.put("string_param", "123"); + eventTags.put("boolean_param", false); + eventTags.put("float_param", 12.3f); + + // call track + optimizely.track(eventType.getKey(), "userId", Collections.emptyMap(), eventTags); + + // setup the event map captor (so we can verify its content) + ArgumentCaptor eventTagCaptor = ArgumentCaptor.forClass(Map.class); + + // verify that the event builder was called with the expected attributes + verify(mockEventBuilder).createConversionEvent(eq(projectConfig), eq(mockBucketer), eq("userId"), + eq(eventType.getId()), eq(eventType.getKey()), + eq(Collections.emptyMap()), eventTagCaptor.capture()); + + Map actualValue = eventTagCaptor.getValue(); + assertThat(actualValue, hasEntry("int_param", eventTags.get("int_param"))); + assertThat(actualValue, hasEntry("string_param", eventTags.get("string_param"))); + assertThat(actualValue, hasEntry("boolean_param", eventTags.get("boolean_param"))); + assertThat(actualValue, hasEntry("float_param", eventTags.get("float_param"))); + + verify(mockEventHandler).dispatchEvent(logEventToDispatch); + } + + /** + * Verify that {@link Optimizely#track(String, String, Map, Map)} called with null event tags will default to + * an empty map when calling @{link EventBuilder#createConversionEvent(ProjectConfig, Bucketer, String, String, String, Map, Map)} + */ + @Test + @SuppressFBWarnings( + value="NP_NONNULL_PARAM_VIOLATION", + justification="testing nullness contract violation") + public void trackEventWithNullEventTags() throws Exception { + String datafile = validConfigJsonV2(); + ProjectConfig projectConfig = validProjectConfigV2(); + EventType eventType = projectConfig.getEventTypes().get(0); + + // setup a mock event builder to return expected conversion params + EventBuilder mockEventBuilder = mock(EventBuilder.class); + + Optimizely optimizely = Optimizely.builder(datafile, mockEventHandler) + .withBucketing(mockBucketer) + .withEventBuilder(mockEventBuilder) + .withConfig(projectConfig) + .withErrorHandler(mockErrorHandler) + .build(); + + Map testParams = new HashMap(); + testParams.put("test", "params"); + LogEvent logEventToDispatch = new LogEvent(RequestMethod.GET, "test_url", testParams, ""); + when(mockEventBuilder.createConversionEvent(eq(projectConfig), eq(mockBucketer), eq("userId"), + eq(eventType.getId()), eq(eventType.getKey()), + eq(Collections.emptyMap()), eq(Collections.emptyMap()))) + .thenReturn(logEventToDispatch); + + logbackVerifier.expectMessage(Level.INFO, "Tracking event \"clicked_cart\" for user \"userId\"."); + logbackVerifier.expectMessage(Level.DEBUG, "Dispatching conversion event to URL test_url with params " + + testParams + " and payload \"\""); + + // call track + optimizely.track(eventType.getKey(), "userId", Collections.emptyMap(), null); + + // verify that the event builder was called with the expected attributes + verify(mockEventBuilder).createConversionEvent(eq(projectConfig), eq(mockBucketer), eq("userId"), + eq(eventType.getId()), eq(eventType.getKey()), + eq(Collections.emptyMap()), eq(Collections.emptyMap())); + + verify(mockEventHandler).dispatchEvent(logEventToDispatch); + } + /** * Verify that {@link Optimizely#track(String, String, Map)} doesn't dispatch an event when no valid experiments * correspond to an event. @@ -1216,43 +1273,6 @@ public void trackLaunchedExperimentDoesNotDispatchEvent() throws Exception { verify(mockEventHandler, never()).dispatchEvent(any(LogEvent.class)); } - /** - * Verify that {@link Optimizely#track(String, String, String)} passes the session ID to - * {@link EventBuilder#createConversionEvent(ProjectConfig, Bucketer, String, String, String, Map, Long, String)} - */ - @Test - public void trackEventWithSessionId() throws Exception { - EventType eventType = noAudienceProjectConfig.getEventTypes().get(0); - - // setup a mock event builder to return expected conversion params - EventBuilder mockEventBuilder = mock(EventBuilder.class); - - Optimizely optimizely = Optimizely.builder(noAudienceDatafile, mockEventHandler) - .withBucketing(mockBucketer) - .withEventBuilder(mockEventBuilder) - .withConfig(noAudienceProjectConfig) - .withErrorHandler(mockErrorHandler) - .build(); - - Map testParams = new HashMap(); - testParams.put("test", "params"); - LogEvent logEventToDispatch = new LogEvent(RequestMethod.GET, "test_url", testParams, ""); - when(mockEventBuilder.createConversionEvent(eq(noAudienceProjectConfig), eq(mockBucketer), eq("userId"), - eq(eventType.getId()), eq(eventType.getKey()), - eq(Collections.emptyMap()), isNull(Long.class), - eq("test_session_id"))) - .thenReturn(logEventToDispatch); - - // call track - optimizely.track(eventType.getKey(), "userId", "test_session_id"); - - // verify that the event builder was called with the expected attributes - verify(mockEventBuilder).createConversionEvent(eq(noAudienceProjectConfig), eq(mockBucketer), eq("userId"), - eq(eventType.getId()), eq(eventType.getKey()), - eq(Collections.emptyMap()), isNull(Long.class), - eq("test_session_id")); - } - //======== getVariation tests ========// /** diff --git a/core-api/src/test/java/com/optimizely/ab/OptimizelyTestV3.java b/core-api/src/test/java/com/optimizely/ab/OptimizelyTestV3.java index 0d9ceed93..f3f556856 100644 --- a/core-api/src/test/java/com/optimizely/ab/OptimizelyTestV3.java +++ b/core-api/src/test/java/com/optimizely/ab/OptimizelyTestV3.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,6 +36,7 @@ import com.optimizely.ab.event.internal.EventBuilderV2; import com.optimizely.ab.internal.LogbackVerifier; import com.optimizely.ab.internal.ProjectValidationUtils; +import com.optimizely.ab.internal.ReservedEventKey; import com.optimizely.ab.notification.NotificationListener; import org.junit.BeforeClass; @@ -139,7 +140,7 @@ public void activateEndToEnd() throws Exception { testParams.put("test", "params"); LogEvent logEventToDispatch = new LogEvent(RequestMethod.GET, "test_url", testParams, ""); when(mockEventBuilder.createImpressionEvent(validProjectConfig, activatedExperiment, bucketedVariation, "userId", - testUserAttributes, null)) + testUserAttributes)) .thenReturn(logEventToDispatch); when(mockBucketer.bucket(activatedExperiment, "userId")) @@ -268,7 +269,7 @@ public void activateWithExperimentKey() throws Exception { testParams.put("test", "params"); LogEvent logEventToDispatch = new LogEvent(RequestMethod.GET, "test_url", testParams, ""); when(mockEventBuilder.createImpressionEvent(eq(validProjectConfig), eq(activatedExperiment), eq(bucketedVariation), - eq("userId"), eq(testUserAttributes), isNull(String.class))) + eq("userId"), eq(testUserAttributes))) .thenReturn(logEventToDispatch); when(mockBucketer.bucket(activatedExperiment, "userId")) @@ -357,8 +358,7 @@ public void activateWithAttributes() throws Exception { testParams.put("test", "params"); LogEvent logEventToDispatch = new LogEvent(RequestMethod.GET, "test_url", testParams, ""); when(mockEventBuilder.createImpressionEvent(eq(validProjectConfig), eq(activatedExperiment), eq(bucketedVariation), - eq("userId"), anyMapOf(String.class, String.class), - isNull(String.class))) + eq("userId"), anyMapOf(String.class, String.class))) .thenReturn(logEventToDispatch); when(mockBucketer.bucket(activatedExperiment, "userId")) @@ -375,8 +375,7 @@ public void activateWithAttributes() throws Exception { // setup the attribute map captor (so we can verify its content) ArgumentCaptor attributeCaptor = ArgumentCaptor.forClass(Map.class); verify(mockEventBuilder).createImpressionEvent(eq(validProjectConfig), eq(activatedExperiment), - eq(bucketedVariation), eq("userId"), attributeCaptor.capture(), - isNull(String.class)); + eq(bucketedVariation), eq("userId"), attributeCaptor.capture()); Map actualValue = attributeCaptor.getValue(); assertThat(actualValue, hasEntry(attribute.getKey(), "attributeValue")); @@ -417,8 +416,7 @@ public void activateWithUnknownAttribute() throws Exception { testParams.put("test", "params"); LogEvent logEventToDispatch = new LogEvent(RequestMethod.GET, "test_url", testParams, ""); when(mockEventBuilder.createImpressionEvent(eq(validProjectConfig), eq(activatedExperiment), eq(bucketedVariation), - eq("userId"), anyMapOf(String.class, String.class), - isNull(String.class))) + eq("userId"), anyMapOf(String.class, String.class))) .thenReturn(logEventToDispatch); when(mockBucketer.bucket(activatedExperiment, "userId")) @@ -440,8 +438,7 @@ public void activateWithUnknownAttribute() throws Exception { // verify that the event builder was called with the expected attributes verify(mockEventBuilder).createImpressionEvent(eq(validProjectConfig), eq(activatedExperiment), - eq(bucketedVariation), eq("userId"), attributeCaptor.capture(), - isNull(String.class)); + eq(bucketedVariation), eq("userId"), attributeCaptor.capture()); Map actualValue = attributeCaptor.getValue(); assertThat(actualValue, not(hasKey("unknownAttribute"))); @@ -477,8 +474,7 @@ public void activateWithNullAttributes() throws Exception { testParams.put("test", "params"); LogEvent logEventToDispatch = new LogEvent(RequestMethod.GET, "test_url", testParams, ""); when(mockEventBuilder.createImpressionEvent(eq(projectConfig), eq(activatedExperiment), eq(bucketedVariation), - eq("userId"), eq(Collections.emptyMap()), - isNull(String.class))) + eq("userId"), eq(Collections.emptyMap()))) .thenReturn(logEventToDispatch); when(mockBucketer.bucket(activatedExperiment, "userId")) @@ -497,8 +493,7 @@ public void activateWithNullAttributes() throws Exception { // setup the attribute map captor (so we can verify its content) ArgumentCaptor attributeCaptor = ArgumentCaptor.forClass(Map.class); verify(mockEventBuilder).createImpressionEvent(eq(projectConfig), eq(activatedExperiment), - eq(bucketedVariation), eq("userId"), attributeCaptor.capture(), - isNull(String.class)); + eq(bucketedVariation), eq("userId"), attributeCaptor.capture()); Map actualValue = attributeCaptor.getValue(); assertThat(actualValue, is(Collections.emptyMap())); @@ -532,8 +527,7 @@ public void activateWithNullAttributeValues() throws Exception { testParams.put("test", "params"); LogEvent logEventToDispatch = new LogEvent(RequestMethod.GET, "test_url", testParams, ""); when(mockEventBuilder.createImpressionEvent(eq(projectConfig), eq(activatedExperiment), eq(bucketedVariation), - eq("userId"), anyMapOf(String.class, String.class), - isNull(String.class))) + eq("userId"), anyMapOf(String.class, String.class))) .thenReturn(logEventToDispatch); when(mockBucketer.bucket(activatedExperiment, "userId")) @@ -551,8 +545,7 @@ public void activateWithNullAttributeValues() throws Exception { // setup the attribute map captor (so we can verify its content) ArgumentCaptor attributeCaptor = ArgumentCaptor.forClass(Map.class); verify(mockEventBuilder).createImpressionEvent(eq(projectConfig), eq(activatedExperiment), - eq(bucketedVariation), eq("userId"), attributeCaptor.capture(), - isNull(String.class)); + eq(bucketedVariation), eq("userId"), attributeCaptor.capture()); Map actualValue = attributeCaptor.getValue(); assertThat(actualValue, hasEntry(attribute.getKey(), null)); @@ -911,8 +904,7 @@ public void trackEventWithAttributes() throws Exception { LogEvent logEventToDispatch = new LogEvent(RequestMethod.GET, "test_url", testParams, ""); when(mockEventBuilder.createConversionEvent(eq(validProjectConfig), eq(mockBucketer), eq("userId"), eq(eventType.getId()), eq(eventType.getKey()), - anyMapOf(String.class, String.class), isNull(Long.class), - isNull(String.class))) + anyMapOf(String.class, String.class), anyMapOf(String.class, Object.class))) .thenReturn(logEventToDispatch); logbackVerifier.expectMessage(Level.INFO, "Tracking event \"clicked_cart\" for user \"userId\"."); @@ -928,8 +920,7 @@ public void trackEventWithAttributes() throws Exception { // verify that the event builder was called with the expected attributes verify(mockEventBuilder).createConversionEvent(eq(validProjectConfig), eq(mockBucketer), eq("userId"), eq(eventType.getId()), eq(eventType.getKey()), - attributeCaptor.capture(), isNull(Long.class), - isNull(String.class)); + attributeCaptor.capture(), anyMapOf(String.class, Object.class)); Map actualValue = attributeCaptor.getValue(); assertThat(actualValue, hasEntry(attribute.getKey(), "attributeValue")); @@ -964,8 +955,7 @@ public void trackEventWithNullAttributes() throws Exception { LogEvent logEventToDispatch = new LogEvent(RequestMethod.GET, "test_url", testParams, ""); when(mockEventBuilder.createConversionEvent(eq(projectConfig), eq(mockBucketer), eq("userId"), eq(eventType.getId()), eq(eventType.getKey()), - eq(Collections.emptyMap()), isNull(Long.class), - isNull(String.class))) + eq(Collections.emptyMap()), eq(Collections.emptyMap()))) .thenReturn(logEventToDispatch); logbackVerifier.expectMessage(Level.INFO, "Tracking event \"clicked_cart\" for user \"userId\"."); @@ -984,8 +974,7 @@ public void trackEventWithNullAttributes() throws Exception { // verify that the event builder was called with the expected attributes verify(mockEventBuilder).createConversionEvent(eq(projectConfig), eq(mockBucketer), eq("userId"), eq(eventType.getId()), eq(eventType.getKey()), - attributeCaptor.capture(), isNull(Long.class), - isNull(String.class)); + attributeCaptor.capture(), eq(Collections.emptyMap())); Map actualValue = attributeCaptor.getValue(); assertThat(actualValue, is(Collections.emptyMap())); @@ -1017,8 +1006,7 @@ public void trackEventWithNullAttributeValues() throws Exception { LogEvent logEventToDispatch = new LogEvent(RequestMethod.GET, "test_url", testParams, ""); when(mockEventBuilder.createConversionEvent(eq(projectConfig), eq(mockBucketer), eq("userId"), eq(eventType.getId()), eq(eventType.getKey()), - anyMapOf(String.class, String.class), isNull(Long.class), - isNull(String.class))) + anyMapOf(String.class, String.class), anyMapOf(String.class, Object.class))) .thenReturn(logEventToDispatch); logbackVerifier.expectMessage(Level.INFO, "Tracking event \"clicked_cart\" for user \"userId\"."); @@ -1036,8 +1024,7 @@ public void trackEventWithNullAttributeValues() throws Exception { // verify that the event builder was called with the expected attributes verify(mockEventBuilder).createConversionEvent(eq(projectConfig), eq(mockBucketer), eq("userId"), eq(eventType.getId()), eq(eventType.getKey()), - attributeCaptor.capture(), isNull(Long.class), - isNull(String.class)); + attributeCaptor.capture(), eq(Collections.emptyMap())); verify(mockEventHandler).dispatchEvent(logEventToDispatch); } @@ -1070,8 +1057,7 @@ public void trackEventWithUnknownAttribute() throws Exception { LogEvent logEventToDispatch = new LogEvent(RequestMethod.GET, "test_url", testParams, ""); when(mockEventBuilder.createConversionEvent(eq(validProjectConfig), eq(mockBucketer), eq("userId"), eq(eventType.getId()), eq(eventType.getKey()), - anyMapOf(String.class, String.class), isNull(Long.class), - isNull(String.class))) + anyMapOf(String.class, String.class), anyMapOf(String.class, Object.class))) .thenReturn(logEventToDispatch); logbackVerifier.expectMessage(Level.INFO, "Tracking event \"clicked_cart\" for user \"userId\"."); @@ -1088,8 +1074,7 @@ public void trackEventWithUnknownAttribute() throws Exception { // verify that the event builder was called with the expected attributes verify(mockEventBuilder).createConversionEvent(eq(validProjectConfig), eq(mockBucketer), eq("userId"), eq(eventType.getId()), eq(eventType.getKey()), - attributeCaptor.capture(), isNull(Long.class), - isNull(String.class)); + attributeCaptor.capture(), anyMapOf(String.class, Object.class)); Map actualValue = attributeCaptor.getValue(); assertThat(actualValue, not(hasKey("unknownAttribute"))); @@ -1097,6 +1082,111 @@ public void trackEventWithUnknownAttribute() throws Exception { verify(mockEventHandler).dispatchEvent(logEventToDispatch); } + /** + * Verify that {@link Optimizely#track(String, String, Map, Map)} passes event features to + * @{link EventBuilder#createConversionEvent(ProjectConfig, Bucketer, String, String, String, Map, Map)} + */ + @Test + public void trackEventWithEventTags() throws Exception { + String datafile = validConfigJsonV3(); + ProjectConfig projectConfig = validProjectConfigV3(); + EventType eventType = projectConfig.getEventTypes().get(0); + + // setup a mock event builder to return expected conversion params + EventBuilder mockEventBuilder = mock(EventBuilder.class); + + Optimizely optimizely = Optimizely.builder(datafile, mockEventHandler) + .withBucketing(mockBucketer) + .withEventBuilder(mockEventBuilder) + .withConfig(projectConfig) + .withErrorHandler(mockErrorHandler) + .build(); + + Map testParams = new HashMap(); + testParams.put("test", "params"); + + Map eventTags = new HashMap(); + eventTags.put("int_param", 123); + eventTags.put("string_param", "123"); + eventTags.put("boolean_param", false); + eventTags.put("float_param", 12.3f); + + LogEvent logEventToDispatch = new LogEvent(RequestMethod.GET, "test_url", testParams, ""); + when(mockEventBuilder.createConversionEvent(eq(projectConfig), eq(mockBucketer), eq("userId"), + eq(eventType.getId()), eq(eventType.getKey()), + anyMapOf(String.class, String.class), eq(eventTags))) + .thenReturn(logEventToDispatch); + + logbackVerifier.expectMessage(Level.INFO, "Tracking event \"clicked_cart\" for user \"userId\"."); + logbackVerifier.expectMessage(Level.DEBUG, "Dispatching conversion event to URL test_url with params " + + testParams + " and payload \"\""); + + // call track + optimizely.track(eventType.getKey(), "userId", Collections.emptyMap(), eventTags); + + // setup the event map captor (so we can verify its content) + ArgumentCaptor eventTagCaptor = ArgumentCaptor.forClass(Map.class); + + // verify that the event builder was called with the expected attributes + verify(mockEventBuilder).createConversionEvent(eq(projectConfig), eq(mockBucketer), eq("userId"), + eq(eventType.getId()), eq(eventType.getKey()), + eq(Collections.emptyMap()), eventTagCaptor.capture()); + + Map actualValue = eventTagCaptor.getValue(); + assertThat(actualValue, hasEntry("int_param", eventTags.get("int_param"))); + assertThat(actualValue, hasEntry("string_param", eventTags.get("string_param"))); + assertThat(actualValue, hasEntry("boolean_param", eventTags.get("boolean_param"))); + assertThat(actualValue, hasEntry("float_param", eventTags.get("float_param"))); + + verify(mockEventHandler).dispatchEvent(logEventToDispatch); + } + + /** + * Verify that {@link Optimizely#track(String, String, Map, Map)} called with null event tags will default to + * an empty map when calling @{link EventBuilder#createConversionEvent(ProjectConfig, Bucketer, String, String, String, Map, Map)} + */ + @Test + @SuppressFBWarnings( + value="NP_NONNULL_PARAM_VIOLATION", + justification="testing nullness contract violation") + public void trackEventWithNullEventTags() throws Exception { + String datafile = validConfigJsonV3(); + ProjectConfig projectConfig = validProjectConfigV3(); + EventType eventType = projectConfig.getEventTypes().get(0); + + // setup a mock event builder to return expected conversion params + EventBuilder mockEventBuilder = mock(EventBuilder.class); + + Optimizely optimizely = Optimizely.builder(datafile, mockEventHandler) + .withBucketing(mockBucketer) + .withEventBuilder(mockEventBuilder) + .withConfig(projectConfig) + .withErrorHandler(mockErrorHandler) + .build(); + + Map testParams = new HashMap(); + testParams.put("test", "params"); + LogEvent logEventToDispatch = new LogEvent(RequestMethod.GET, "test_url", testParams, ""); + when(mockEventBuilder.createConversionEvent(eq(projectConfig), eq(mockBucketer), eq("userId"), + eq(eventType.getId()), eq(eventType.getKey()), + eq(Collections.emptyMap()), eq(Collections.emptyMap()))) + .thenReturn(logEventToDispatch); + + logbackVerifier.expectMessage(Level.INFO, "Tracking event \"clicked_cart\" for user \"userId\"."); + logbackVerifier.expectMessage(Level.DEBUG, "Dispatching conversion event to URL test_url with params " + + testParams + " and payload \"\""); + + // call track + optimizely.track(eventType.getKey(), "userId", Collections.emptyMap(), null); + + // verify that the event builder was called with the expected attributes + verify(mockEventBuilder).createConversionEvent(eq(projectConfig), eq(mockBucketer), eq("userId"), + eq(eventType.getId()), eq(eventType.getKey()), + eq(Collections.emptyMap()), eq(Collections.emptyMap())); + + verify(mockEventHandler).dispatchEvent(logEventToDispatch); + } + /** * Verify that {@link Optimizely#track(String, String)} passes through revenue. */ @@ -1119,26 +1209,27 @@ public void trackEventWithRevenue() throws Exception { Map testParams = new HashMap(); testParams.put("test", "params"); + Map eventTags= new HashMap(); + eventTags.put(ReservedEventKey.REVENUE.toString(), revenue); LogEvent logEventToDispatch = new LogEvent(RequestMethod.GET, "test_url", testParams, ""); when(mockEventBuilder.createConversionEvent(eq(validProjectConfig), eq(mockBucketer), eq("userId"), eq(eventType.getId()), eq(eventType.getKey()), - eq(Collections.emptyMap()), eq(revenue), - isNull(String.class))) + eq(Collections.emptyMap()), eq(eventTags))) .thenReturn(logEventToDispatch); // call track optimizely.track(eventType.getKey(), "userId", revenue); - // setup the revenue captor (so we can verify its content) - ArgumentCaptor revenueCaptor = ArgumentCaptor.forClass(Long.class); + // setup the event tag map captor (so we can verify its content) + ArgumentCaptor eventTagCaptor = ArgumentCaptor.forClass(Map.class); // verify that the event builder was called with the expected revenue verify(mockEventBuilder).createConversionEvent(eq(validProjectConfig), eq(mockBucketer), eq("userId"), eq(eventType.getId()), eq(eventType.getKey()), eq(Collections.emptyMap()), - revenueCaptor.capture(), isNull(String.class)); + eventTagCaptor.capture()); - Long actualValue = revenueCaptor.getValue(); + Long actualValue = (Long)eventTagCaptor.getValue().get(ReservedEventKey.REVENUE.toString()); assertThat(actualValue, is(revenue)); verify(mockEventHandler).dispatchEvent(logEventToDispatch); @@ -1700,14 +1791,14 @@ public void addNotificationListener() throws Exception { testParams.put("test", "params"); LogEvent logEventToDispatch = new LogEvent(RequestMethod.GET, "test_url", testParams, ""); when(mockEventBuilder.createImpressionEvent(validProjectConfig, activatedExperiment, - bucketedVariation, userId, attributes, null)) + bucketedVariation, userId, attributes)) .thenReturn(logEventToDispatch); when(mockBucketer.bucket(activatedExperiment, userId)) .thenReturn(bucketedVariation); when(mockEventBuilder.createImpressionEvent(validProjectConfig, activatedExperiment, - bucketedVariation, userId, attributes, null)) + bucketedVariation, userId, attributes)) .thenReturn(logEventToDispatch); // Add listener @@ -1731,8 +1822,7 @@ public void addNotificationListener() throws Exception { when(mockEventBuilder.createConversionEvent(eq(validProjectConfig), eq(mockBucketer), eq(userId), eq(eventType.getId()), eq(eventKey), - anyMapOf(String.class, String.class), isNull(Long.class), - isNull(String.class))) + anyMapOf(String.class, String.class), anyMapOf(String.class, Object.class))) .thenReturn(logEventToDispatch); optimizely.track(eventKey, userId, attributes); @@ -1767,14 +1857,14 @@ public void removeNotificationListener() throws Exception { testParams.put("test", "params"); LogEvent logEventToDispatch = new LogEvent(RequestMethod.GET, "test_url", testParams, ""); when(mockEventBuilder.createImpressionEvent(validProjectConfig, activatedExperiment, - bucketedVariation, userId, attributes, null)) + bucketedVariation, userId, attributes)) .thenReturn(logEventToDispatch); when(mockBucketer.bucket(activatedExperiment, userId)) .thenReturn(bucketedVariation); when(mockEventBuilder.createImpressionEvent(validProjectConfig, activatedExperiment, bucketedVariation, userId, - attributes, null)) + attributes)) .thenReturn(logEventToDispatch); // Add and remove listener @@ -1834,14 +1924,14 @@ public void clearNotificationListeners() throws Exception { testParams.put("test", "params"); LogEvent logEventToDispatch = new LogEvent(RequestMethod.GET, "test_url", testParams, ""); when(mockEventBuilder.createImpressionEvent(validProjectConfig, activatedExperiment, - bucketedVariation, userId, attributes, null)) + bucketedVariation, userId, attributes)) .thenReturn(logEventToDispatch); when(mockBucketer.bucket(activatedExperiment, userId)) .thenReturn(bucketedVariation); when(mockEventBuilder.createImpressionEvent(validProjectConfig, activatedExperiment, bucketedVariation, userId, - attributes, null)) + attributes)) .thenReturn(logEventToDispatch); NotificationListener listener = mock(NotificationListener.class); diff --git a/core-api/src/test/java/com/optimizely/ab/bucketing/BucketerTest.java b/core-api/src/test/java/com/optimizely/ab/bucketing/BucketerTest.java index f22d6a7cf..f98763505 100644 --- a/core-api/src/test/java/com/optimizely/ab/bucketing/BucketerTest.java +++ b/core-api/src/test/java/com/optimizely/ab/bucketing/BucketerTest.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/test/java/com/optimizely/ab/bucketing/internal/MurmurHash3Test.java b/core-api/src/test/java/com/optimizely/ab/bucketing/internal/MurmurHash3Test.java index 65f7b9ae9..bf86a31f9 100644 --- a/core-api/src/test/java/com/optimizely/ab/bucketing/internal/MurmurHash3Test.java +++ b/core-api/src/test/java/com/optimizely/ab/bucketing/internal/MurmurHash3Test.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/test/java/com/optimizely/ab/categories/ExhaustiveTest.java b/core-api/src/test/java/com/optimizely/ab/categories/ExhaustiveTest.java index 9e9494fae..484112a79 100644 --- a/core-api/src/test/java/com/optimizely/ab/categories/ExhaustiveTest.java +++ b/core-api/src/test/java/com/optimizely/ab/categories/ExhaustiveTest.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/test/java/com/optimizely/ab/config/ProjectConfigTest.java b/core-api/src/test/java/com/optimizely/ab/config/ProjectConfigTest.java index a91e09452..69ca282a9 100644 --- a/core-api/src/test/java/com/optimizely/ab/config/ProjectConfigTest.java +++ b/core-api/src/test/java/com/optimizely/ab/config/ProjectConfigTest.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/test/java/com/optimizely/ab/config/ProjectConfigTestUtils.java b/core-api/src/test/java/com/optimizely/ab/config/ProjectConfigTestUtils.java index 483100f47..261da80f9 100644 --- a/core-api/src/test/java/com/optimizely/ab/config/ProjectConfigTestUtils.java +++ b/core-api/src/test/java/com/optimizely/ab/config/ProjectConfigTestUtils.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/test/java/com/optimizely/ab/config/VariationTest.java b/core-api/src/test/java/com/optimizely/ab/config/VariationTest.java index 1e145e07d..5a76f51ca 100644 --- a/core-api/src/test/java/com/optimizely/ab/config/VariationTest.java +++ b/core-api/src/test/java/com/optimizely/ab/config/VariationTest.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/test/java/com/optimizely/ab/config/audience/AudienceConditionEvaluationTest.java b/core-api/src/test/java/com/optimizely/ab/config/audience/AudienceConditionEvaluationTest.java index 6bbb91d36..101193558 100644 --- a/core-api/src/test/java/com/optimizely/ab/config/audience/AudienceConditionEvaluationTest.java +++ b/core-api/src/test/java/com/optimizely/ab/config/audience/AudienceConditionEvaluationTest.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/test/java/com/optimizely/ab/config/parser/DefaultConfigParserTest.java b/core-api/src/test/java/com/optimizely/ab/config/parser/DefaultConfigParserTest.java index f2e1a2df1..5911932f8 100644 --- a/core-api/src/test/java/com/optimizely/ab/config/parser/DefaultConfigParserTest.java +++ b/core-api/src/test/java/com/optimizely/ab/config/parser/DefaultConfigParserTest.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/test/java/com/optimizely/ab/config/parser/GsonConfigParserTest.java b/core-api/src/test/java/com/optimizely/ab/config/parser/GsonConfigParserTest.java index f66c3e401..9a182c371 100644 --- a/core-api/src/test/java/com/optimizely/ab/config/parser/GsonConfigParserTest.java +++ b/core-api/src/test/java/com/optimizely/ab/config/parser/GsonConfigParserTest.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/test/java/com/optimizely/ab/config/parser/JacksonConfigParserTest.java b/core-api/src/test/java/com/optimizely/ab/config/parser/JacksonConfigParserTest.java index 3adac6c70..f2c8ce8d0 100644 --- a/core-api/src/test/java/com/optimizely/ab/config/parser/JacksonConfigParserTest.java +++ b/core-api/src/test/java/com/optimizely/ab/config/parser/JacksonConfigParserTest.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/test/java/com/optimizely/ab/config/parser/JsonConfigParserTest.java b/core-api/src/test/java/com/optimizely/ab/config/parser/JsonConfigParserTest.java index 064871471..cb9088ea0 100644 --- a/core-api/src/test/java/com/optimizely/ab/config/parser/JsonConfigParserTest.java +++ b/core-api/src/test/java/com/optimizely/ab/config/parser/JsonConfigParserTest.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/test/java/com/optimizely/ab/config/parser/JsonSimpleConfigParserTest.java b/core-api/src/test/java/com/optimizely/ab/config/parser/JsonSimpleConfigParserTest.java index 48f679e7a..b8bc9c373 100644 --- a/core-api/src/test/java/com/optimizely/ab/config/parser/JsonSimpleConfigParserTest.java +++ b/core-api/src/test/java/com/optimizely/ab/config/parser/JsonSimpleConfigParserTest.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/test/java/com/optimizely/ab/event/NoopEventHandlerTest.java b/core-api/src/test/java/com/optimizely/ab/event/NoopEventHandlerTest.java index 972120565..9b1f29e9c 100644 --- a/core-api/src/test/java/com/optimizely/ab/event/NoopEventHandlerTest.java +++ b/core-api/src/test/java/com/optimizely/ab/event/NoopEventHandlerTest.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/test/java/com/optimizely/ab/event/internal/EventBuilderV1Test.java b/core-api/src/test/java/com/optimizely/ab/event/internal/EventBuilderV1Test.java index 64f86a401..fc3c3cc09 100644 --- a/core-api/src/test/java/com/optimizely/ab/event/internal/EventBuilderV1Test.java +++ b/core-api/src/test/java/com/optimizely/ab/event/internal/EventBuilderV1Test.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,6 +26,7 @@ import com.optimizely.ab.config.Variation; import com.optimizely.ab.internal.ProjectValidationUtils; +import com.optimizely.ab.internal.ReservedEventKey; import org.junit.Test; import java.util.Arrays; @@ -162,9 +163,10 @@ public void createConversionParamsWithRevenue() throws Exception { } Map attributeMap = Collections.singletonMap(attribute.getKey(), "value"); + Map eventTagsMap = Collections.singletonMap(ReservedEventKey.REVENUE.toString(), revenue); LogEvent conversionEvent = builder.createConversionEvent(projectConfig, mockBucketAlgorithm, "userId", eventType.getId(), eventType.getKey(), attributeMap, - revenue); + eventTagsMap); Map requestParams = conversionEvent.getRequestParams(); // we're not going to verify everything, just revenue and the associated goals diff --git a/core-api/src/test/java/com/optimizely/ab/event/internal/EventBuilderV2Test.java b/core-api/src/test/java/com/optimizely/ab/event/internal/EventBuilderV2Test.java index 3b76e8184..ffcc8ddc0 100644 --- a/core-api/src/test/java/com/optimizely/ab/event/internal/EventBuilderV2Test.java +++ b/core-api/src/test/java/com/optimizely/ab/event/internal/EventBuilderV2Test.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -37,16 +37,19 @@ import com.optimizely.ab.internal.LogbackVerifier; import com.optimizely.ab.internal.ProjectValidationUtils; +import com.optimizely.ab.internal.ReservedEventKey; import org.junit.Rule; import org.junit.Test; import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Map; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.Matchers.closeTo; +import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNull; @@ -176,27 +179,6 @@ public void createImpressionEventAndroidTVClientEngineClientVersion() throws Exc assertThat(impression.getClientVersion(), is(clientVersion)); } - /** - * Verify that passing a non-null session ID to - * {@link EventBuilder#createImpressionEvent(ProjectConfig, Experiment, Variation, String, Map, String)} properly - * constructs an impression payload with the session ID specified. - */ - @Test - public void createImpressionEventWithSessionId() throws Exception { - ProjectConfig projectConfig = ProjectConfigTestUtils.validProjectConfigV2(); - Experiment activatedExperiment = projectConfig.getExperiments().get(0); - Variation bucketedVariation = activatedExperiment.getVariations().get(0); - Attribute attribute = projectConfig.getAttributes().get(0); - String userId = "userId"; - Map attributeMap = Collections.singletonMap(attribute.getKey(), "value"); - String sessionId = "sessionid"; - - LogEvent impressionEvent = builder.createImpressionEvent(projectConfig, activatedExperiment, bucketedVariation, - userId, attributeMap, sessionId); - Impression impression = gson.fromJson(impressionEvent.getBody(), Impression.class); - assertThat(impression.getSessionId(), is(sessionId)); - } - /** * Verify {@link Conversion} event creation */ @@ -221,8 +203,11 @@ public void createConversionEvent() throws Exception { } Map attributeMap = Collections.singletonMap(attribute.getKey(), "value"); + Map eventTagMap = new HashMap(); + eventTagMap.put("boolean_param", false); + eventTagMap.put("string_param", "123"); LogEvent conversionEvent = builder.createConversionEvent(projectConfig, mockBucketAlgorithm, userId, - eventType.getId(), eventType.getKey(), attributeMap); + eventType.getId(), eventType.getKey(), attributeMap, eventTagMap); List expectedLayerStates = new ArrayList(); @@ -252,12 +237,21 @@ public void createConversionEvent() throws Exception { Feature feature = new Feature(attribute.getId(), attribute.getKey(), Feature.CUSTOM_ATTRIBUTE_FEATURE_TYPE, "value", true); List expectedUserFeatures = Collections.singletonList(feature); + + // Event Features + List expectedEventFeatures = new ArrayList(); + expectedEventFeatures.add(new Feature("", "boolean_param", Feature.EVENT_FEATURE_TYPE, + false, false)); + expectedEventFeatures.add(new Feature("", "string_param", Feature.EVENT_FEATURE_TYPE, + "123", false)); + assertThat(conversion.getUserFeatures(), is(expectedUserFeatures)); assertThat(conversion.getLayerStates(), is(expectedLayerStates)); assertThat(conversion.getEventEntityId(), is(eventType.getId())); assertThat(conversion.getEventName(), is(eventType.getKey())); assertThat(conversion.getEventMetrics(), is(Collections.emptyList())); - assertThat(conversion.getEventFeatures(), is(Collections.emptyList())); + assertTrue(conversion.getEventFeatures().containsAll(expectedEventFeatures)); + assertTrue(expectedEventFeatures.containsAll(conversion.getEventFeatures())); assertFalse(conversion.getIsGlobalHoldback()); assertThat(conversion.getAnonymizeIP(), is(projectConfig.getAnonymizeIP())); assertThat(conversion.getClientEngine(), is(ClientEngine.JAVA_SDK.getClientEngineValue())); @@ -285,9 +279,11 @@ public void createConversionParamsWithRevenue() throws Exception { } Map attributeMap = Collections.singletonMap(attribute.getKey(), "value"); + Map eventTagMap = new HashMap(); + eventTagMap.put(ReservedEventKey.REVENUE.toString(), revenue); LogEvent conversionEvent = builder.createConversionEvent(projectConfig, mockBucketAlgorithm, "userId", eventType.getId(), eventType.getKey(), attributeMap, - revenue); + eventTagMap); Conversion conversion = gson.fromJson(conversionEvent.getBody(), Conversion.class); @@ -472,33 +468,4 @@ public void createConversionEventForEventUsingLaunchedExperiment() throws Except // event will be null assertNull(conversionEvent); } - - /** - * Verify that passing a non-null session ID to - * {@link EventBuilder#createConversionEvent(ProjectConfig, Bucketer, String, String, String, Map, Long, String)} - * properly constructs an impression payload with the session ID specified. - */ - @Test - public void createConversionEventWithSessionId() throws Exception { - EventBuilderV2 builder = new EventBuilderV2(ClientEngine.ANDROID_SDK, "0.0.0"); - ProjectConfig projectConfig = ProjectConfigTestUtils.validProjectConfigV2(); - Attribute attribute = projectConfig.getAttributes().get(0); - EventType eventType = projectConfig.getEventTypes().get(0); - String userId = "userId"; - String sessionId = "sessionid"; - - Bucketer mockBucketAlgorithm = mock(Bucketer.class); - for (Experiment experiment : projectConfig.getExperiments()) { - when(mockBucketAlgorithm.bucket(experiment, userId)) - .thenReturn(experiment.getVariations().get(0)); - } - - Map attributeMap = Collections.singletonMap(attribute.getKey(), "value"); - LogEvent conversionEvent = builder.createConversionEvent(projectConfig, mockBucketAlgorithm, userId, - eventType.getId(), eventType.getKey(), attributeMap, - null, sessionId); - - Conversion conversion = gson.fromJson(conversionEvent.getBody(), Conversion.class); - assertThat(conversion.getSessionId(), is(sessionId)); - } } diff --git a/core-api/src/test/java/com/optimizely/ab/event/internal/serializer/GsonSerializerTest.java b/core-api/src/test/java/com/optimizely/ab/event/internal/serializer/GsonSerializerTest.java index e7977092a..a69340482 100644 --- a/core-api/src/test/java/com/optimizely/ab/event/internal/serializer/GsonSerializerTest.java +++ b/core-api/src/test/java/com/optimizely/ab/event/internal/serializer/GsonSerializerTest.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/test/java/com/optimizely/ab/event/internal/serializer/JacksonSerializerTest.java b/core-api/src/test/java/com/optimizely/ab/event/internal/serializer/JacksonSerializerTest.java index e29c5ebaa..03792b9e2 100644 --- a/core-api/src/test/java/com/optimizely/ab/event/internal/serializer/JacksonSerializerTest.java +++ b/core-api/src/test/java/com/optimizely/ab/event/internal/serializer/JacksonSerializerTest.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/test/java/com/optimizely/ab/event/internal/serializer/JsonSerializerTest.java b/core-api/src/test/java/com/optimizely/ab/event/internal/serializer/JsonSerializerTest.java index 64c7988e9..f76d02f77 100644 --- a/core-api/src/test/java/com/optimizely/ab/event/internal/serializer/JsonSerializerTest.java +++ b/core-api/src/test/java/com/optimizely/ab/event/internal/serializer/JsonSerializerTest.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/test/java/com/optimizely/ab/event/internal/serializer/JsonSimpleSerializerTest.java b/core-api/src/test/java/com/optimizely/ab/event/internal/serializer/JsonSimpleSerializerTest.java index c2e0775f5..da286b2ba 100644 --- a/core-api/src/test/java/com/optimizely/ab/event/internal/serializer/JsonSimpleSerializerTest.java +++ b/core-api/src/test/java/com/optimizely/ab/event/internal/serializer/JsonSimpleSerializerTest.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/test/java/com/optimizely/ab/event/internal/serializer/SerializerTestUtils.java b/core-api/src/test/java/com/optimizely/ab/event/internal/serializer/SerializerTestUtils.java index 456ec149b..e39464fc5 100644 --- a/core-api/src/test/java/com/optimizely/ab/event/internal/serializer/SerializerTestUtils.java +++ b/core-api/src/test/java/com/optimizely/ab/event/internal/serializer/SerializerTestUtils.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/test/java/com/optimizely/ab/internal/ProjectValidationUtilsTestV1.java b/core-api/src/test/java/com/optimizely/ab/internal/ProjectValidationUtilsTestV1.java index 771635034..5bfce4fe2 100644 --- a/core-api/src/test/java/com/optimizely/ab/internal/ProjectValidationUtilsTestV1.java +++ b/core-api/src/test/java/com/optimizely/ab/internal/ProjectValidationUtilsTestV1.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/test/java/com/optimizely/ab/internal/ProjectValidationUtilsTestV2.java b/core-api/src/test/java/com/optimizely/ab/internal/ProjectValidationUtilsTestV2.java index f7828eb77..c4b954742 100644 --- a/core-api/src/test/java/com/optimizely/ab/internal/ProjectValidationUtilsTestV2.java +++ b/core-api/src/test/java/com/optimizely/ab/internal/ProjectValidationUtilsTestV2.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/test/java/com/optimizely/ab/notification/NotificationBroadcasterTest.java b/core-api/src/test/java/com/optimizely/ab/notification/NotificationBroadcasterTest.java index 9bfa36d05..d754c4233 100644 --- a/core-api/src/test/java/com/optimizely/ab/notification/NotificationBroadcasterTest.java +++ b/core-api/src/test/java/com/optimizely/ab/notification/NotificationBroadcasterTest.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-httpclient-impl/src/main/java/com/optimizely/ab/HttpClientUtils.java b/core-httpclient-impl/src/main/java/com/optimizely/ab/HttpClientUtils.java index d26249b55..bb7ca3e76 100644 --- a/core-httpclient-impl/src/main/java/com/optimizely/ab/HttpClientUtils.java +++ b/core-httpclient-impl/src/main/java/com/optimizely/ab/HttpClientUtils.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-httpclient-impl/src/main/java/com/optimizely/ab/NamedThreadFactory.java b/core-httpclient-impl/src/main/java/com/optimizely/ab/NamedThreadFactory.java index 098d4f605..8e1443c8a 100644 --- a/core-httpclient-impl/src/main/java/com/optimizely/ab/NamedThreadFactory.java +++ b/core-httpclient-impl/src/main/java/com/optimizely/ab/NamedThreadFactory.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-httpclient-impl/src/main/java/com/optimizely/ab/event/AsyncEventHandler.java b/core-httpclient-impl/src/main/java/com/optimizely/ab/event/AsyncEventHandler.java index 881dabe72..6cce2fc00 100644 --- a/core-httpclient-impl/src/main/java/com/optimizely/ab/event/AsyncEventHandler.java +++ b/core-httpclient-impl/src/main/java/com/optimizely/ab/event/AsyncEventHandler.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016, Optimizely and contributors + * Copyright 2016-2017, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/gradle/HEADER b/gradle/HEADER index 95949fc29..1e8f53dac 100644 --- a/gradle/HEADER +++ b/gradle/HEADER @@ -1,5 +1,5 @@ - Copyright ${year}, Optimizely and contributors + Copyright ${start_year}-${end_year}, Optimizely and contributors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/gradle/license.gradle b/gradle/license.gradle index 7ae4e4bf3..5e46c7a89 100644 --- a/gradle/license.gradle +++ b/gradle/license.gradle @@ -3,6 +3,7 @@ subprojects { license { header rootProject.file('gradle/HEADER') excludes(['**/*.properties', '**/*.txt', '**/*.conf', '**/*.xml', '**/*.json', '**/LogbackVerifier.java']) - ext.year = '2016' // year that the project was created + ext.start_year = '2016' // year that the project was created + ext.end_year = Calendar.getInstance().get(Calendar.YEAR) } }