Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import io.split.android.client.ServiceEndpoints;
import io.split.android.client.SplitClientConfig;
import io.split.android.client.SyncConfig;
import io.split.android.client.fallback.FallbackTreatmentsConfiguration;
import io.split.android.client.impressions.ImpressionListener;
import io.split.android.client.network.CertificatePinningConfiguration;
import io.split.android.client.network.DevelopmentSslConfig;
Expand All @@ -15,7 +16,6 @@
import io.split.android.client.shared.UserConsent;
import io.split.android.client.utils.logger.Logger;
import io.split.android.client.utils.logger.SplitLogLevel;
import io.split.android.client.fallback.FallbackTreatmentsConfiguration;

public class TestableSplitConfigBuilder {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,8 @@
import io.split.android.client.api.Key;
import io.split.android.client.events.SplitEvent;
import io.split.android.client.events.SplitEventTask;
import io.split.android.client.fallback.FallbackConfiguration;
import io.split.android.client.fallback.FallbackTreatment;
import io.split.android.client.fallback.FallbackTreatmentsConfiguration;
import io.split.android.client.fallback.FallbackTreatment;
import io.split.android.client.impressions.Impression;
import io.split.android.client.impressions.ImpressionListener;
import io.split.android.client.service.impressions.ImpressionsMode;
Expand Down Expand Up @@ -239,11 +238,8 @@ public MockResponse dispatch(RecordedRequest request) {

Map<String, FallbackTreatment> byFlag = new HashMap<>();
byFlag.put("any_flag", new FallbackTreatment("OFF_FALLBACK"));
FallbackConfiguration byFactory = FallbackConfiguration.builder()
.byFlag(byFlag)
.build();
FallbackTreatmentsConfiguration fbConfig = FallbackTreatmentsConfiguration.builder()
.byFactory(byFactory)
.byFlag(byFlag)
.build();

SplitClientConfig config = buildConfig(fbConfig, true, 1);
Expand Down Expand Up @@ -301,11 +297,8 @@ public MockResponse dispatch(RecordedRequest request) {
};
mWebServer.setDispatcher(dispatcher);

FallbackConfiguration byFactory = FallbackConfiguration.builder()
.global(new FallbackTreatment("OFF_FALLBACK"))
.build();
FallbackTreatmentsConfiguration fbConfig = FallbackTreatmentsConfiguration.builder()
.byFactory(byFactory)
.global(new FallbackTreatment("OFF_FALLBACK"))
.build();

SplitClientConfig config = buildConfig(fbConfig);
Expand All @@ -329,13 +322,10 @@ public MockResponse dispatch(RecordedRequest request) {
public void case4_FlagOverrideBeatsFactoryDefaultReturnsOnFallbackForOverriddenAndOffFallbackForOthers() throws Exception {
Map<String, FallbackTreatment> byFlag = new HashMap<>();
byFlag.put("my_flag", new FallbackTreatment("ON_FALLBACK"));
FallbackConfiguration byFactory = FallbackConfiguration.builder()
FallbackTreatmentsConfiguration fbConfig = FallbackTreatmentsConfiguration.builder()
.global(new FallbackTreatment("OFF_FALLBACK"))
.byFlag(byFlag)
.build();
FallbackTreatmentsConfiguration fbConfig = FallbackTreatmentsConfiguration.builder()
.byFactory(byFactory)
.build();

SplitClientConfig config = buildConfig(fbConfig);

Expand Down Expand Up @@ -363,11 +353,8 @@ public void case4_FlagOverrideBeatsFactoryDefaultReturnsOnFallbackForOverriddenA
public void case2_factoryWideOverrideReturnsFallbackForUnknownFlagsAndTwoKeys() throws Exception {
// endpoints provided by helper in buildConfig

FallbackConfiguration byFactory = FallbackConfiguration.builder()
.global(new FallbackTreatment("FALLBACK_TREATMENT"))
.build();
FallbackTreatmentsConfiguration fbConfig = FallbackTreatmentsConfiguration.builder()
.byFactory(byFactory)
.global(new FallbackTreatment("FALLBACK_TREATMENT"))
.build();

SplitClientConfig config = buildConfig(fbConfig);
Expand Down Expand Up @@ -409,11 +396,8 @@ public void case3_factorySpecificOverrideReturnsFallbackForOneFlagAndControlForO

Map<String, FallbackTreatment> byFlag = new HashMap<>();
byFlag.put("non_existent_flag", new FallbackTreatment("FALLBACK_TREATMENT"));
FallbackConfiguration byFactory = FallbackConfiguration.builder()
.byFlag(byFlag)
.build();
FallbackTreatmentsConfiguration fbConfig = FallbackTreatmentsConfiguration.builder()
.byFactory(byFactory)
.byFlag(byFlag)
.build();

SplitClientConfig config = SplitClientConfig.builder()
Expand Down Expand Up @@ -466,13 +450,10 @@ public void case7_fallbackDynamicConfigPropagationTreatmentAndConfigReturned() t

Map<String, FallbackTreatment> byFlag = new HashMap<>();
byFlag.put("my_flag", new FallbackTreatment("ON_FALLBACK", "{\"flag\":true}"));
FallbackConfiguration byFactory = FallbackConfiguration.builder()
FallbackTreatmentsConfiguration fbConfig = FallbackTreatmentsConfiguration.builder()
.global(new FallbackTreatment("OFF_FALLBACK", "{\"global\":true}"))
.byFlag(byFlag)
.build();
FallbackTreatmentsConfiguration fbConfig = FallbackTreatmentsConfiguration.builder()
.byFactory(byFactory)
.build();

SplitClientConfig config = SplitClientConfig.builder()
.serviceEndpoints(endpoints)
Expand Down Expand Up @@ -545,11 +526,8 @@ public MockResponse dispatch(RecordedRequest request) {
mWebServer.setDispatcher(dispatcher);

// Configure global fallback so unknown flags return a fallback treatment
FallbackConfiguration byFactory = FallbackConfiguration.builder()
.global(new FallbackTreatment("OFF_FALLBACK"))
.build();
FallbackTreatmentsConfiguration fbConfig = FallbackTreatmentsConfiguration.builder()
.byFactory(byFactory)
.global(new FallbackTreatment("OFF_FALLBACK"))
.build();

final List<Impression> capturedImpressions = Collections.synchronizedList(new ArrayList<>());
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/io/split/android/client/EvaluatorImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import io.split.android.client.dtos.ConditionType;
import io.split.android.client.exceptions.ChangeNumberExceptionWrapper;
import io.split.android.client.fallback.FallbackConfiguration;
import io.split.android.client.fallback.FallbackTreatmentsConfiguration;
import io.split.android.client.fallback.FallbackTreatment;
import io.split.android.client.fallback.FallbackTreatmentsCalculator;
import io.split.android.client.fallback.FallbackTreatmentsCalculatorImpl;
Expand All @@ -23,7 +23,7 @@ public class EvaluatorImpl implements Evaluator {
private final FallbackTreatmentsCalculator mFallbackCalculator;

public EvaluatorImpl(SplitsStorage splitsStorage, SplitParser splitParser) {
this(splitsStorage, splitParser, new FallbackTreatmentsCalculatorImpl(FallbackConfiguration.builder().build()));
this(splitsStorage, splitParser, new FallbackTreatmentsCalculatorImpl(FallbackTreatmentsConfiguration.builder().build()));
}

public EvaluatorImpl(SplitsStorage splitsStorage, SplitParser splitParser, FallbackTreatmentsCalculator fallbackCalculator) {
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package io.split.android.client.fallback;

import static io.split.android.client.utils.Utils.checkNotNull;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

Expand All @@ -12,10 +14,10 @@ public final class FallbackTreatmentsCalculatorImpl implements FallbackTreatment
private static final String LABEL_PREFIX = "fallback - ";

@NonNull
private final FallbackConfiguration mConfig;
private final FallbackTreatmentsConfiguration mConfig;

public FallbackTreatmentsCalculatorImpl(@NonNull FallbackConfiguration config) {
mConfig = config;
public FallbackTreatmentsCalculatorImpl(@NonNull FallbackTreatmentsConfiguration config) {
mConfig = checkNotNull(config);
}

@NonNull
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,49 +3,111 @@
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

public final class FallbackTreatmentsConfiguration {

@Nullable
private final FallbackConfiguration mByFactory;
private final FallbackTreatment mGlobal;
private final Map<String, FallbackTreatment> mByFlag;

private FallbackTreatmentsConfiguration(@Nullable FallbackConfiguration byFactory) {
mByFactory = byFactory;
private FallbackTreatmentsConfiguration(@Nullable FallbackTreatment global,
@Nullable Map<String, FallbackTreatment> byFlag) {
mGlobal = global;
if (byFlag == null || byFlag.isEmpty()) {
mByFlag = Collections.emptyMap();
} else {
mByFlag = Collections.unmodifiableMap(new HashMap<>(byFlag));
}
}

@Nullable
public FallbackConfiguration getByFactory() {
return mByFactory;
public FallbackTreatment getGlobal() {
return mGlobal;
}

public Map<String, FallbackTreatment> getByFlag() {
return mByFlag;
}

/**
* Creates a new {@link Builder} for {@link FallbackTreatmentsConfiguration}.
* Use this to provide an optional global fallback and flag-specific fallbacks.
*/
public static Builder builder() {
return new Builder();
}

public static final class Builder {
@Nullable
private FallbackConfiguration mByFactory;
private FallbackTreatment mGlobal;
@Nullable
private Map<String, FallbackTreatment> mByFlag;
private FallbacksSanitizer mSanitizer;

private Builder() {
mGlobal = null;
mByFlag = null;
mSanitizer = new FallbacksSanitizerImpl();
}

@VisibleForTesting
Builder sanitizer(FallbacksSanitizer sanitizer) {
mSanitizer = sanitizer;
/**
* Sets an optional global fallback treatment to be used when no flag-specific
* fallback exists for a given flag. This value is returned only in place of
* the "control" treatment.
*
* @param global optional global {@link FallbackTreatment}
* @return this builder instance
*/
public Builder global(@Nullable FallbackTreatment global) {
mGlobal = global;
return this;
}

public Builder byFactory(@Nullable FallbackConfiguration byFactory) {
mByFactory = byFactory;
/**
* Sets optional flag-specific fallback treatments, where keys are flag names.
* These take precedence over the global fallback.
*
* @param byFlag map of flag name to {@link FallbackTreatment}; may be null or empty
* @return this builder instance
*/
public Builder byFlag(@Nullable Map<String, FallbackTreatment> byFlag) {
mByFlag = byFlag;
return this;
}

/**
* Builds a {@link FallbackTreatmentsConfiguration} for the configured values.
*
* @return a new immutable {@link FallbackTreatmentsConfiguration}
*/
public FallbackTreatmentsConfiguration build() {
FallbackConfiguration sanitized = (mByFactory == null)
? null
: mSanitizer.sanitize(mByFactory);
return new FallbackTreatmentsConfiguration(sanitized);
FallbackTreatment sanitizedGlobal = mSanitizer.sanitizeGlobal(mGlobal);
Map<String, FallbackTreatment> sanitizedByFlag = mSanitizer.sanitizeByFlag(mByFlag);
return new FallbackTreatmentsConfiguration(sanitizedGlobal, sanitizedByFlag);
}

@VisibleForTesting
Builder sanitizer(FallbacksSanitizer sanitizer) {
mSanitizer = sanitizer;
return this;
}
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
FallbackTreatmentsConfiguration that = (FallbackTreatmentsConfiguration) o;
return Objects.equals(mGlobal, that.mGlobal) &&
Objects.equals(mByFlag, that.mByFlag);
}

@Override
public int hashCode() {
return Objects.hash(mGlobal, mByFlag);
}
}
Loading
Loading