io.getunleash.variant.VariantUtil Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of unleash-client-java Show documentation
Show all versions of unleash-client-java Show documentation
A client library for Unleash
package io.getunleash.variant;
import io.getunleash.FeatureToggle;
import io.getunleash.UnleashContext;
import io.getunleash.Variant;
import io.getunleash.lang.Nullable;
import io.getunleash.strategy.StrategyUtils;
import java.util.List;
import java.util.Optional;
import java.util.Random;
import java.util.function.Predicate;
public final class VariantUtil {
// Utility class
private VariantUtil() {}
private static Predicate overrideMatchesContext(UnleashContext context) {
return (override) -> {
Optional contextValue;
switch (override.getContextName()) {
case "userId":
{
contextValue = context.getUserId();
break;
}
case "sessionId":
{
contextValue = context.getSessionId();
break;
}
case "remoteAddress":
{
contextValue = context.getRemoteAddress();
break;
}
default:
contextValue =
Optional.ofNullable(
context.getProperties().get(override.getContextName()));
break;
}
return override.getValues().contains(contextValue.orElse(""));
};
}
private static Optional getOverride(
List variants, UnleashContext context) {
return variants.stream()
.filter(
variant ->
variant.getOverrides().stream()
.anyMatch(overrideMatchesContext(context)))
.findFirst();
}
private static String getIdentifier(UnleashContext context) {
return context.getUserId()
.orElse(
context.getSessionId()
.orElse(
context.getRemoteAddress()
.orElse(Double.toString(Math.random()))));
}
private static String randomString() {
int randSeed = new Random().nextInt(100000);
return "" + randSeed;
}
private static String getSeed(UnleashContext unleashContext, Optional stickiness) {
return stickiness
.map(s -> unleashContext.getByName(s).orElse(randomString()))
.orElse(getIdentifier(unleashContext));
}
public static Variant selectVariant(
@Nullable FeatureToggle featureToggle, UnleashContext context, Variant defaultVariant) {
if (featureToggle == null) {
return defaultVariant;
}
List variants = featureToggle.getVariants();
int totalWeight = variants.stream().mapToInt(VariantDefinition::getWeight).sum();
if (totalWeight == 0) {
return defaultVariant;
}
Optional variantOverride = getOverride(variants, context);
if (variantOverride.isPresent()) {
return variantOverride.get().toVariant();
}
Optional customStickiness =
variants.stream()
.filter(
f ->
f.getStickiness() != null
&& !"default".equals(f.getStickiness()))
.map(VariantDefinition::getStickiness)
.findFirst();
int target =
StrategyUtils.getNormalizedNumber(
getSeed(context, customStickiness), featureToggle.getName(), totalWeight);
int counter = 0;
for (final VariantDefinition definition : featureToggle.getVariants()) {
if (definition.getWeight() != 0) {
counter += definition.getWeight();
if (counter >= target) {
return definition.toVariant();
}
}
}
// Should not happen
return defaultVariant;
}
}