Skip to content
Merged
26 changes: 14 additions & 12 deletions src/main/java/dev/openfeature/sdk/FlagEvaluationDetails.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package dev.openfeature.sdk;

import java.util.Optional;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
Expand All @@ -26,7 +25,7 @@ public class FlagEvaluationDetails<T> implements BaseEvaluation<T> {
private String errorMessage;

@Builder.Default
private ImmutableMetadata flagMetadata = ImmutableMetadata.builder().build();
private ImmutableMetadata flagMetadata = ImmutableMetadata.EMPTY;

/**
* Generate detail payload from the provider response.
Expand All @@ -37,15 +36,18 @@ public class FlagEvaluationDetails<T> implements BaseEvaluation<T> {
* @return detail payload
*/
public static <T> FlagEvaluationDetails<T> from(ProviderEvaluation<T> providerEval, String flagKey) {
return FlagEvaluationDetails.<T>builder()
.flagKey(flagKey)
.value(providerEval.getValue())
.variant(providerEval.getVariant())
.reason(providerEval.getReason())
.errorMessage(providerEval.getErrorMessage())
.errorCode(providerEval.getErrorCode())
.flagMetadata(Optional.ofNullable(providerEval.getFlagMetadata())
.orElse(ImmutableMetadata.builder().build()))
.build();
var flagMetadata = providerEval.getFlagMetadata();
if (flagMetadata == null) {
flagMetadata = ImmutableMetadata.EMPTY;
}

return new FlagEvaluationDetails<>(
flagKey,
providerEval.getValue(),
providerEval.getVariant(),
providerEval.getReason(),
providerEval.getErrorCode(),
providerEval.getErrorMessage(),
flagMetadata);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@
@SuppressWarnings("checkstyle:MissingJavadocType")
@lombok.Value
@Builder
public class FlagEvaluationOptions {

Check warning on line 12 in src/main/java/dev/openfeature/sdk/FlagEvaluationOptions.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

A Singleton implementation was detected. Make sure the use of the Singleton pattern is required and the implementation is the right one for the context.

See more on https://sonarcloud.io/project/issues?id=open-feature_java-sdk&issues=AZq7FD4JV_4DfXvPH881&open=AZq7FD4JV_4DfXvPH881&pullRequest=1741

public static final FlagEvaluationOptions EMPTY =
FlagEvaluationOptions.builder().build();

@Singular
List<Hook> hooks;

Expand Down
11 changes: 11 additions & 0 deletions src/main/java/dev/openfeature/sdk/HashMapUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package dev.openfeature.sdk;

import java.util.HashMap;

class HashMapUtils {
private HashMapUtils() {}

static <K, V> HashMap<K, V> forEntries(int expectedEntries) {
return new HashMap<>((int) Math.ceil(expectedEntries / .75));
}
}
5 changes: 3 additions & 2 deletions src/main/java/dev/openfeature/sdk/ImmutableContext.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package dev.openfeature.sdk;

import dev.openfeature.sdk.internal.ExcludeFromGeneratedCoverageReport;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
Expand All @@ -20,7 +21,7 @@
@SuppressWarnings("PMD.BeanMembersShouldSerialize")
public final class ImmutableContext implements EvaluationContext {

public static final ImmutableContext EMPTY = new ImmutableContext();
public static final ImmutableContext EMPTY = new ImmutableContext(Collections.emptyMap());

@Delegate(excludes = DelegateExclusions.class)
private final ImmutableStructure structure;
Expand Down Expand Up @@ -58,7 +59,7 @@ public ImmutableContext(Map<String, Value> attributes) {
* @param attributes evaluation context attributes
*/
public ImmutableContext(String targetingKey, Map<String, Value> attributes) {
if (targetingKey != null && !targetingKey.trim().isEmpty()) {
if (targetingKey != null && !targetingKey.isBlank()) {
this.structure = new ImmutableStructure(targetingKey, attributes);
} else {
this.structure = new ImmutableStructure(attributes);
Expand Down
19 changes: 12 additions & 7 deletions src/main/java/dev/openfeature/sdk/ImmutableStructure.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.Set;
import lombok.EqualsAndHashCode;
import lombok.ToString;
Expand Down Expand Up @@ -69,15 +68,21 @@ private static Map<String, Value> copyAttributes(Map<String, Value> in) {
}

private static Map<String, Value> copyAttributes(Map<String, Value> in, String targetingKey) {
Map<String, Value> copy = new HashMap<>();
Map<String, Value> copy;
if (in != null) {
var numMappings = in.size();
if (targetingKey != null) {
numMappings++;
}
copy = HashMapUtils.forEntries(numMappings);
for (Entry<String, Value> entry : in.entrySet()) {
copy.put(
entry.getKey(),
Optional.ofNullable(entry.getValue())
.map((Value val) -> val.clone())
.orElse(null));
var key = entry.getKey();
var value = entry.getValue();
Value cloned = value == null ? null : value.clone();
copy.put(key, cloned);
}
} else {
copy = new HashMap<>(targetingKey == null ? 0 : 1);
}
if (targetingKey != null) {
copy.put(EvaluationContext.TARGETING_KEY, new Value(targetingKey));
Expand Down
23 changes: 12 additions & 11 deletions src/main/java/dev/openfeature/sdk/OpenFeatureClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -163,8 +163,13 @@ private <T> FlagEvaluationDetails<T> evaluateFlag(
FlagEvaluationDetails<T> details = null;
HookSupportData hookSupportData = new HookSupportData();

var flagOptions = ObjectUtils.defaultIfNull(
options, () -> FlagEvaluationOptions.builder().build());
FlagEvaluationOptions flagOptions;
if (options == null) {
flagOptions = FlagEvaluationOptions.EMPTY;
} else {
flagOptions = options;
}

hookSupportData.hints = Collections.unmodifiableMap(flagOptions.getHookHints());
var context = new LayeredEvaluationContext(
openfeatureApi.getEvaluationContext(),
Expand Down Expand Up @@ -323,8 +328,7 @@ public FlagEvaluationDetails<Boolean> getBooleanDetails(String key, Boolean defa

@Override
public FlagEvaluationDetails<Boolean> getBooleanDetails(String key, Boolean defaultValue, EvaluationContext ctx) {
return getBooleanDetails(
key, defaultValue, ctx, FlagEvaluationOptions.builder().build());
return getBooleanDetails(key, defaultValue, ctx, FlagEvaluationOptions.EMPTY);
}

@Override
Expand Down Expand Up @@ -356,8 +360,7 @@ public FlagEvaluationDetails<String> getStringDetails(String key, String default

@Override
public FlagEvaluationDetails<String> getStringDetails(String key, String defaultValue, EvaluationContext ctx) {
return getStringDetails(
key, defaultValue, ctx, FlagEvaluationOptions.builder().build());
return getStringDetails(key, defaultValue, ctx, FlagEvaluationOptions.EMPTY);
}

@Override
Expand Down Expand Up @@ -389,8 +392,7 @@ public FlagEvaluationDetails<Integer> getIntegerDetails(String key, Integer defa

@Override
public FlagEvaluationDetails<Integer> getIntegerDetails(String key, Integer defaultValue, EvaluationContext ctx) {
return getIntegerDetails(
key, defaultValue, ctx, FlagEvaluationOptions.builder().build());
return getIntegerDetails(key, defaultValue, ctx, FlagEvaluationOptions.EMPTY);
}

@Override
Expand Down Expand Up @@ -454,8 +456,7 @@ public FlagEvaluationDetails<Value> getObjectDetails(String key, Value defaultVa

@Override
public FlagEvaluationDetails<Value> getObjectDetails(String key, Value defaultValue, EvaluationContext ctx) {
return getObjectDetails(
key, defaultValue, ctx, FlagEvaluationOptions.builder().build());
return getObjectDetails(key, defaultValue, ctx, FlagEvaluationOptions.EMPTY);
}

@Override
Expand All @@ -466,7 +467,7 @@ public FlagEvaluationDetails<Value> getObjectDetails(

@Override
public ClientMetadata getMetadata() {
return () -> domain;
return this::getDomain;
}

/**
Expand Down
Loading